package com.sc.nft.helper;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.config.lianlian.LLianPayClient;
import com.sc.nft.config.sand.SandConfig;
import com.sc.nft.dao.DaoCustomerOpenAccountDao;
import com.sc.nft.dao.IdcardInfoDao;
import com.sc.nft.dao.LlExchangePhoneDao;
import com.sc.nft.dao.StaticDataDao;
import com.sc.nft.dao.UserBankCardDao;
import com.sc.nft.dao.UserInfoDao;
import com.sc.nft.dao.WithdrawBankCardDao;
import com.sc.nft.dto.llian.BasicInfoDTO;
import com.sc.nft.dto.llian.LinkedAcctInfoDTO;
import com.sc.nft.dto.llian.LlRandomPwdDTO;
import com.sc.nft.entity.BankBindApply;
import com.sc.nft.entity.DaoAccountBankInfo;
import com.sc.nft.entity.DaoAccountLegalPerson;
import com.sc.nft.entity.DaoCustomerOpenAccount;
import com.sc.nft.entity.DaoTransfer;
import com.sc.nft.entity.DaoWithdrawRecord;
import com.sc.nft.entity.IdcardInfo;
import com.sc.nft.entity.LlExchangePhone;
import com.sc.nft.entity.LlModifyUserInfo;
import com.sc.nft.entity.LlUserExt;
import com.sc.nft.entity.MallPayOrderRecord;
import com.sc.nft.entity.OrderSplitFlow;
import com.sc.nft.entity.PayOrder;
import com.sc.nft.entity.SandBizRecord;
import com.sc.nft.entity.SandTransferRecord;
import com.sc.nft.entity.SandWithdrawRecord;
import com.sc.nft.entity.UserBankCard;
import com.sc.nft.entity.UserCreatorInfo;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.WithdrawBankCard;
import com.sc.nft.entity.dto.SaasTaskBurialPointDTO;
import com.sc.nft.entity.vo.PwdElementVO;
import com.sc.nft.enums.*;
import com.sc.nft.enums.llian.LlEnum;
import com.sc.nft.enums.llian.LlUploadFileTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.LlUserExtService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.BankCardUtil;
import com.sc.nft.util.OrderNoUtil;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.sc.nft.config.lianlian.LlConfig.anonymousBindCardNotify;
import static com.sc.nft.config.lianlian.LlConfig.apiUrl;
import static com.sc.nft.config.lianlian.LlConfig.bindCardNotify;
import static com.sc.nft.config.lianlian.LlConfig.businessOpenAccountNotifyUrl;
import static com.sc.nft.config.lianlian.LlConfig.daoWithdrawNotify;
import static com.sc.nft.config.lianlian.LlConfig.fileUrl;
import static com.sc.nft.config.lianlian.LlConfig.merchantNo;
import static com.sc.nft.config.lianlian.LlConfig.modifyUserNotifyUrl;
import static com.sc.nft.config.lianlian.LlConfig.openAccountNotifyUrl;
import static com.sc.nft.config.lianlian.LlConfig.openAccountReturnUrl;
import static com.sc.nft.config.lianlian.LlConfig.pgwUrl;
import static com.sc.nft.config.lianlian.LlConfig.unAnonymousBindCardNotify;
import static com.sc.nft.config.lianlian.LlConfig.unBindCardNotify;
import static com.sc.nft.config.lianlian.LlConfig.withdrawNotify;
import static com.sc.nft.enums.PayMethodEnum.LL_BALANCE_PAY;

@Component
@RequiredArgsConstructor
@Slf4j
public class LlPayHelper {

    private final LlUserExtService llUserExtService;
    private final IdcardInfoDao idcardInfoDao;
    private final WithdrawBankCardDao withdrawBankCardDao;
    private final StaticDataDao staticDataDao;
    private final UserBankCardDao userBankCardDao;
    private final LlExchangePhoneDao exchangePhoneDao;
    private final UserInfoDao userInfoDao;
    private final DaoCustomerOpenAccountDao customerOpenAccountDao;
    private final MessageQueueHelper messageQueueHelper;

    public static final String SUCCESS_CODE = "0000";

    @Value("${pay.url.web}")
    private String webUrl;
    @Value("${pay.url.merchantWebUrl}")
    private String merchantWebUrl;


    @Value("${pay.llConfig.exchange_phone_notify_url}")
    private String exchangePhoneNotify;


    /**
     * 开户申请
     *
     * @param userInfo
     * @param isWeb
     * @return
     */
    public String openAccount(UserInfo userInfo, Boolean isWeb) {
        LlUserExt userExt = llUserExtService.getByUserId(userInfo.getId());
        IdcardInfo idcardInfo = idcardInfoDao.getByUserIdAndIsPass(userInfo.getId());
        Assert.notNull(idcardInfo, () -> new GlobalRunTimeException(ErrorCode.USER_NOT_SM));
        DateTime now = DateTime.now();
        if (ObjectUtil.isNotNull(userExt)) {
            if (userExt.getStatus() == AccountStatusEnum.OPENING) {
                if (now.isBefore(userExt.getExpirationTime())) {
                    return userExt.getGatewayUrl();
                }
                userExt.setUserKey(IdUtil.getSnowflakeNextIdStr());
            } else if (userExt.getStatus() == AccountStatusEnum.SUCCESS) {
                Assert.isFalse(userExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException(ErrorCode.OPEN_ACCOUNT_EXISTS));
            }
        } else {
            userExt = new LlUserExt();
            userExt.setUserId(userInfo.getId());
            userExt.setUserKey(IdUtil.getSnowflakeNextIdStr());
        }
        userExt.setStatus(AccountStatusEnum.OPENING);
        userExt.setSeqNo(OrderNoUtil.getOrderNo());
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("user_id", userExt.getUserKey());
        params.put("txn_seqno", userExt.getSeqNo());
        params.put("flag_chnl", "H5");
        if (BooleanUtil.isTrue(isWeb)) {
            params.put("return_url", openAccountReturnUrl);
        } else {
            params.put("return_url", SandConfig.FAST_RETURN_URL);
        }
        params.put("return_url", params.getString("return_url") + "?jump=page");
        params.put("notify_url", openAccountNotifyUrl);
        params.put("user_type", "INNERUSER");
        JSONObject basicInfo = new JSONObject();
        basicInfo.put("reg_phone", userInfo.getUserTel());
        basicInfo.put("user_name", idcardInfo.getName());
        basicInfo.put("id_type", "ID_CARD");
        basicInfo.put("id_no", idcardInfo.getCardId());
        basicInfo.put("occupation", "19"); //固定其他 省事儿
        params.put("basicInfo", basicInfo);
        JSONObject accountInfo = new JSONObject();
        accountInfo.put("account_type", "PERSONAL_PAYMENT_ACCOUNT");
        accountInfo.put("account_need_level", "V3");
        params.put("accountInfo", accountInfo);
        JSONObject result = sendRequest(userInfo.getId(), pgwUrl, LlEnum.OPEN_ACCOUNT, params);
        userExt.setGatewayUrl(result.getString("gateway_url") + "&header=Y");
        userExt.setExpirationTime(DateUtil.offsetMinute(now, 1));
        userExt.insertOrUpdate();
        return userExt.getGatewayUrl();
    }

    /**
     * 开户成功
     *
     * @param seqNo
     * @param userStatus
     * @param userNo
     * @param remark
     */
    public void openAccountSuccess(String seqNo, String linkedAgrtno, String userStatus, String userNo, String remark, BasicInfoDTO basicInfo, LinkedAcctInfoDTO linkedAcctInfo, String regPhone) {
        LlUserExt userExt = llUserExtService.getBySeqNo(seqNo);
        Assert.notNull(userExt, () -> new GlobalRunTimeException("未找到开户信息"));
        Assert.isTrue(userExt.getStatus() == AccountStatusEnum.OPENING, () -> new GlobalRunTimeException("当前状态不是开户中"));
        userExt.setRegPhone(regPhone);
        if (StrUtil.equals(userStatus, "NORMAL")) {
            userExt.setStatus(AccountStatusEnum.SUCCESS);
            userExt.setUserNo(userNo);
        } else {
            userExt.setStatus(AccountStatusEnum.FAIl);
            userExt.setRemark(remark);
        }
        userExt.updateById();
        if (userExt.getStatus() == AccountStatusEnum.SUCCESS) {
            WithdrawBankCard withdrawBankCard = new WithdrawBankCard();
            withdrawBankCard.setUserId(userExt.getUserId());
            withdrawBankCard.setBankName(bankMapping.get(linkedAcctInfo.getLinked_bankcode()));
            withdrawBankCard.setBankCardNo(linkedAcctInfo.getLinked_acctno());
            withdrawBankCard.setRelatedCardNo(linkedAgrtno);
            withdrawBankCard.setName(basicInfo.getUser_name());
            withdrawBankCard.setMobile(linkedAcctInfo.getLinked_phone());
            withdrawBankCard.setIdentityNo(basicInfo.getId_no());
            withdrawBankCard.setStatus(true);
            withdrawBankCard.setChannel(WalletChannelEnum.LL);
            withdrawBankCard.setBindId(0L);
            withdrawBankCard.insert();
            SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
            // 开户成功之后,发送任务判定
            messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userExt.getUserId(), SaasTaskTypeEnum.OPEN_WALLET_FOR_THE_FIRST_TIME, BigDecimal.ONE, 1, null), SaasTaskTypeEnum.OPEN_WALLET_FOR_THE_FIRST_TIME.name());
            // 开户成功之后,发送任务判定
            messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userExt.getUserId(), SaasTaskTypeEnum.FIRST_TIME_OPEN_WALLET_INVITATION, BigDecimal.ONE, 1, null), SaasTaskTypeEnum.FIRST_TIME_OPEN_WALLET_INVITATION.name());
        }

    }

    /**
     * 匿名绑卡验证
     *
     * @param userInfo
     * @param bankBindApply
     * @param smsCode
     * @return
     */
    public JSONObject anonymousBindVerify(UserInfo userInfo, BankBindApply bankBindApply, String smsCode) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("user_id", userInfo.getUserUuid());
        params.put("txn_seqno", bankBindApply.getApplyNo());
        params.put("token", bankBindApply.getSdMsgNo());
        params.put("verify_code", smsCode);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.ANONYMOUS_BIND_CARD_VERIFY, params);
    }


    /**
     * 提现卡绑定
     *
     * @param userInfo
     * @param cardNo
     * @param identityNo
     * @param name
     * @param phoneNo
     */
    public Long bindCard(UserInfo userInfo, String cardNo, String identityNo, String name, String phoneNo, String pwd, String randomKey) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("请先完成连连支付开户"));
        WithdrawBankCard userCard = withdrawBankCardDao.findUserCard(userInfo.getId(), cardNo, WalletChannelEnum.LL);
        if (ObjectUtil.isNotNull(userCard)) {
            throw new GlobalRunTimeException("此卡已经绑定过了");
        }
        BankBindApply bankBindApply = new BankBindApply();
        bankBindApply.setUserId(userInfo.getId());
        bankBindApply.setStatus(BankBindApplyStatus.NOT_APPROVAL);
        bankBindApply.setApplyNo(OrderNoUtil.getOrderNo());
        bankBindApply.setType(BankBindApplyType.BIND);
        bankBindApply.setCardNo(cardNo);
        bankBindApply.setName(name);
        bankBindApply.setChannel(PayChannelEnum.LL_PAY);
        bankBindApply.setCardType(CardTypeEnum.WITHDRAW);
        bankBindApply.setPhoneNo(phoneNo);
        bankBindApply.setCertificateNo(identityNo);
        bankBindApply.setBankName(BankCardUtil.getBankNameByCardNo(cardNo));
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("user_id", llUserExt.getUserKey());
        params.put("txn_seqno", bankBindApply.getApplyNo());
        params.put("linked_acctno", bankBindApply.getCardNo());
        params.put("linked_phone", bankBindApply.getPhoneNo());
        params.put("password", pwd);
        params.put("notify_url", bindCardNotify);
        params.put("random_key", randomKey);
        JSONObject result = sendRequest(userInfo.getId(), apiUrl, LlEnum.BIND_CARD_APPLY, params);
        bankBindApply.setSdMsgNo(result.getString("token"));
        bankBindApply.insert();
        return bankBindApply.getId();
    }

    /**
     * 提现卡绑定验证
     *
     * @param userInfo
     */
    public Long bindCardVerify(UserInfo userInfo, BankBindApply bankBindApply, String smsCode) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("请先完成连连支付开户"));
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("user_id", llUserExt.getUserKey());
        params.put("txn_seqno", bankBindApply.getApplyNo());
        params.put("token", bankBindApply.getSdMsgNo());
        params.put("verify_code", smsCode);
        JSONObject result = sendRequest(userInfo.getId(), apiUrl, LlEnum.BIND_CARD_VERIFY, params);
        WithdrawBankCard userCard = new WithdrawBankCard();
        userCard.setUserId(userInfo.getId());
        userCard.setBankName(BankCardUtil.getBankNameByCardNo(bankBindApply.getCardNo()));
        userCard.setBankCardNo(bankBindApply.getCardNo());
        userCard.setChannel(WalletChannelEnum.LL);
        userCard.setRelatedCardNo(result.getString("linked_agrtno"));
        userCard.setBindId(bankBindApply.getId());
        userCard.setName(bankBindApply.getName());
        userCard.setMobile(bankBindApply.getPhoneNo());
        userCard.setIdentityNo(bankBindApply.getCertificateNo());
        userCard.setStatus(true);
        userCard.insert();
        return bankBindApply.getId();
    }

    /**
     * 账户手机号变更
     *
     * @param userInfo
     */
    public Long changePhone(UserInfo userInfo, String oldPhone, String newPhone, String password, String randomKey) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("请先完成连连支付开户"));
        LlExchangePhone exchangePhone = new LlExchangePhone();
        exchangePhone.setUserId(userInfo.getId());
        exchangePhone.setOldPhone(oldPhone);
        exchangePhone.setNewPhone(newPhone);
        exchangePhone.setSeqNo(OrderNoUtil.getOrderNo());
        exchangePhone.setStatus(false);
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("user_id", llUserExt.getUserKey());
        params.put("txn_seqno", exchangePhone.getSeqNo());
        params.put("reg_phone", oldPhone);
        params.put("reg_phone_new", newPhone);
        params.put("notify_url", exchangePhoneNotify);
        params.put("password", password);
        params.put("random_key", randomKey);
        JSONObject result = sendRequest(userInfo.getId(), apiUrl, LlEnum.EXCHANGE_PHONE, params);
        exchangePhone.setToken(result.getString("token"));
        exchangePhone.insert();

        return exchangePhone.getId();
    }

    /**
     * 账户手机号变更
     *
     * @param userInfo
     */
    public void exchangePhoneVerify(UserInfo userInfo, Long id, String verifyCode) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("请先完成连连支付开户"));
        LlExchangePhone exchangePhone = exchangePhoneDao.getById(id);
        Assert.isTrue(ObjectUtil.isNotNull(exchangePhone) && exchangePhone.getUserId().longValue() == userInfo.getId().longValue(), () -> new GlobalRunTimeException("未找到换绑记录"));

        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("user_id", llUserExt.getUserKey());
        params.put("txn_seqno", exchangePhone.getSeqNo());
        params.put("token", exchangePhone.getToken());
        params.put("verify_code_new", verifyCode);

        JSONObject result = sendRequest(userInfo.getId(), apiUrl, LlEnum.EXCHANGE_PHONE_VERIFY, params);

    }

    /**
     * 解绑个人银行卡
     *
     * @return
     */
    public void unBindCard(UserInfo userInfo, WithdrawBankCard userCard, String password, String randomKey) {
        if (userCard.getBindId().longValue() != 0L) {
            LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
            Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
            JSONObject params = new JSONObject();
            params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
            params.put("txn_time", params.getString("timestamp"));
            params.put("user_id", llUserExt.getUserKey());
            params.put("txn_seqno", OrderNoUtil.getOrderNo());
            params.put("linked_acctno", userCard.getBankCardNo());
            params.put("notify_url", unBindCardNotify);
            params.put("password", password);
            params.put("random_key", randomKey);
            JSONObject result = sendRequest(llUserExt.getUserId(), apiUrl, LlEnum.UN_BIND_CARD, params);
        }
        userCard.setStatus(false);
        userCard.updateById();
    }


    /**
     * 创建订单
     *
     * @return
     */
    public JSONObject createOrder(UserInfo userInfo, PayOrder payOrder) {
        JSONObject params = new JSONObject();
        params.put("user_id", userInfo.getUserUuid());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_type", "GENERAL_CONSUME");
        params.put("notify_url", payOrder.getNotifyUrl());
        params.put("return_url", payOrder.getFrontUrl());
        params.put("user_type", "ANONYMOUS");
        long between = DateUtil.between(payOrder.getCloseTime(), DateTime.now(), DateUnit.SECOND);
        long time = DateUtil.between(payOrder.getCloseTime(), DateTime.now(), DateUnit.MINUTE);
        if (time == 0 && between < 15) {
            throw new GlobalRunTimeException("订单已超时");
        }
        params.put("pay_expire", time > 0 ? time : 1);
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", payOrder.getTradeNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", payOrder.getPayAmount().toPlainString());
        params.put("orderInfo", orderInfo);
        JSONObject payeeInfo = new JSONObject();
        payeeInfo.put("payee_id", merchantNo);
        payeeInfo.put("payee_type", "MERCHANT");
        payeeInfo.put("payee_accttype", "MCHOWN");
        payeeInfo.put("payee_amount", payOrder.getPayAmount().toPlainString());
        params.put("payeeInfo", payeeInfo);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.CREATE_ORDER, params);

    }

    /**
     * 创建订单-担保交易
     *
     * @return
     */
    public JSONObject createOrderForSecuredConsume(UserInfo userInfo, PayOrder payOrder, LlUserExt userExt, PayMethodEnum payMethodEnum) {
        JSONObject params = new JSONObject();
        params.put("user_id", payMethodEnum.equals(LL_BALANCE_PAY) ? userExt.getUserKey() : userInfo.getUserUuid());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_type", "SECURED_CONSUME");
        params.put("notify_url", payOrder.getNotifyUrl());
        params.put("return_url", payOrder.getFrontUrl());
        params.put("user_type", payMethodEnum.equals(LL_BALANCE_PAY) ? "REGISTERED" : "ANONYMOUS");
        long between = DateUtil.between(payOrder.getCloseTime(), DateTime.now(), DateUnit.SECOND);
        long time = DateUtil.between(payOrder.getCloseTime(), DateTime.now(), DateUnit.MINUTE);
        if (time == 0 && between < 15) {
            throw new GlobalRunTimeException("订单已超时");
        }
        params.put("pay_expire", time > 0 ? time : 1);
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", payOrder.getTradeNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", payOrder.getPayAmount().toPlainString());
        params.put("orderInfo", orderInfo);
//        JSONObject payeeInfo = new JSONObject();
//        payeeInfo.put("payee_id", merchantNo);
//        payeeInfo.put("payee_type", "MERCHANT");
//        payeeInfo.put("payee_accttype", "MCHOWN");
//        payeeInfo.put("payee_amount", payOrder.getPayAmount().toPlainString());
//        params.put("payeeInfo", payeeInfo);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.CREATE_ORDER, params);

    }

    /**
     * 担保交易确认
     *
     * @param userInfo  付款人信息
     * @param userExt
     * @param splitFlow TODO 此处要改成分账订单 暂时工具类用支付单占位
     * @return
     */

    public JSONObject confirmSecuredConsume(UserInfo userInfo, LlUserExt userExt, OrderSplitFlow splitFlow, PayOrder payOrder, LlUserExt payUserExt) {
        JSONObject params = new JSONObject();
        params.put("user_id", payOrder.getPayType().equals(LL_BALANCE_PAY) ? payUserExt.getUserKey() : userInfo.getUserUuid());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("oid_partner", merchantNo);
        params.put("confirm_mode", "PART");
        //-----原订单信息
        JSONObject originalOrderInfo = new JSONObject();
        //商户系统唯一交易流水号
        originalOrderInfo.put("txn_seqno", splitFlow.getPayNo());
        //(8,2) 精确到小数点后两位
        originalOrderInfo.put("total_amount", splitFlow.getOrderAmount());
        params.put("originalOrderInfo", originalOrderInfo);

        //-----确认订单信息
        JSONObject confirmOrderInfo = new JSONObject();
        //确认订单号
        confirmOrderInfo.put("confirm_seqno", splitFlow.getSplitNo());
        //确认时间yyyyMMddHHmmss
        confirmOrderInfo.put("confirm_time", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        //确认金额（8,2）
        confirmOrderInfo.put("confirm_amount", splitFlow.getSettleAmount());
        params.put("confirmOrderInfo", confirmOrderInfo);

        //-----收款方信息 需要区分接收资金的人是个人还是平台商户,分账单需要提现此字段
        JSONObject payeeInfo = new JSONObject();
        payeeInfo.put("payee_id", splitFlow.getUserId() == 0L ? merchantNo : userExt.getUserKey());
        payeeInfo.put("payee_type", splitFlow.getUserId() == 0L ? "MERCHANT" : "USER");
        //(8,2)精确到小数点后2位
        payeeInfo.put("payee_amount", splitFlow.getSettleAmount());
        params.put("payeeInfo", payeeInfo);
        splitFlow.setReqParams(JSONObject.toJSONString(params));
        return sendSplitRequest(splitFlow.getUserId(), apiUrl, LlEnum.SECURED_CONSUME_CONFIRM, params);
    }

    /**
     * 分账查询
     * 分账单对象
     *
     * @return
     */

    public JSONObject querySecuredConsume(UserInfo userInfo, PayOrder payOrder) {
        JSONObject params = new JSONObject();
        //yyyyMMddHHmmss
        params.put("timestamp", "");
        params.put("oid_partner", merchantNo);
        params.put("accp_txno", "分账单号");
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.SECURED_CONSUME_QUERY, params);
    }


    public JSONObject createMallOrder(UserInfo userInfo, MallPayOrderRecord payOrder) {
        JSONObject params = new JSONObject();
        params.put("user_id", userInfo.getUserUuid());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_type", "GENERAL_CONSUME");
        params.put("notify_url", payOrder.getNotifyUrl());
        params.put("return_url", payOrder.getNotifyUrl() + "?jump=page&type=1&orderNo=" + payOrder.getOrderNo());
        params.put("user_type", "ANONYMOUS");
        long between = DateUtil.between(payOrder.getCloseTime(), DateTime.now(), DateUnit.SECOND);
        long time = DateUtil.between(payOrder.getCloseTime(), DateTime.now(), DateUnit.MINUTE);
        if (time == 0 && between < 15) {
            throw new GlobalRunTimeException("订单已超时");
        }
        params.put("pay_expire", time > 0 ? time : 1);
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", payOrder.getTradeNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", payOrder.getPayAmount().toPlainString());
        params.put("orderInfo", orderInfo);
        JSONObject payeeInfo = new JSONObject();
        payeeInfo.put("payee_id", merchantNo);
        payeeInfo.put("payee_type", "MERCHANT");
        payeeInfo.put("payee_accttype", "MCHOWN");
        payeeInfo.put("payee_amount", payOrder.getPayAmount().toPlainString());
        params.put("payeeInfo", payeeInfo);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.CREATE_ORDER, params);

    }

    /**
     * 随机密码因子
     *
     * @return
     */
    public LlRandomPwdDTO getRandom(UserInfo userInfo, Integer type, AppTypeEnum appType) {
        JSONObject params = new JSONObject();
        if (type.intValue() == 2) {
            LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
            Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
            params.put("user_id", llUserExt.getUserKey());
        } else {
            params.put("user_id", userInfo.getUserUuid());
        }
        params.put("app_name", "玛特宇宙");
        switch (appType) {
            case IOS:
                params.put("flag_chnl", appType.name());
                params.put("pkg_name", "com.kekefanyi.CCA");
                break;
            case ANDROID:
                params.put("flag_chnl", appType.name());
                params.put("pkg_name", "com.sc.scxm");
                break;
            case H5:
                params.put("flag_chnl", appType.name());
                params.put("pkg_name", webUrl);
                break;
        }
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        JSONObject result = sendRequest(userInfo.getId(), apiUrl, LlEnum.RANDOM_PWD, params);
        return new LlRandomPwdDTO(result.getString("random_key"), result.getString("random_value"), result.getString("license"), result.getString("rsa_public_content"), null);
    }


    /**
     * 随机密码因子
     *
     * @return
     */
    public LlRandomPwdDTO getDaoRandom(Long operatorId, String daoUuid) {
        JSONObject params = new JSONObject();
        params.put("user_id", daoUuid);
        params.put("app_name", merchantWebUrl);
        params.put("flag_chnl", "PCH5");
        params.put("pkg_name", merchantWebUrl);
        params.put("encrypt_algorithm", "SM2");
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        JSONObject result = sendRequest(operatorId, apiUrl, LlEnum.RANDOM_PWD, params);
        return new LlRandomPwdDTO(result.getString("random_key"), result.getString("random_value"), result.getString("license"), null, result.getString("sm2_key_hex"));
    }

    /**
     * 密码控件token
     *
     * @return
     */
    public PwdElementVO getPwdElement(UserInfo userInfo, Integer scene, BigDecimal amount) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        PwdElementVO pwdElementVO = new PwdElementVO();
        pwdElementVO.setUserId(llUserExt.getUserKey());
        pwdElementVO.setOidPartner(merchantNo);
        if (scene.intValue() == 1) {//设置密码
            params.put("password_scene", "setting_password");
            params.put("user_id", llUserExt.getUserKey());
        } else if (scene.intValue() == 2) {//提现
            if (amount == null || NumberUtil.isLessOrEqual(amount, BigDecimal.ZERO)) {
                throw new GlobalRunTimeException("提现金额不正确");
            }

            params.put("user_id", llUserExt.getUserKey());
            params.put("amount", amount.toPlainString());
            params.put("password_scene", "cashout_password");
            IdcardInfo idcardInfo = idcardInfoDao.getByUserIdAndIsPass(userInfo.getId());
            params.put("pyee_name", idcardInfo.getName());
        } else if (scene.intValue() == 3) {//换绑卡
            params.put("user_id", llUserExt.getUserKey());
            params.put("password_scene", "bind_card_password");
        } else if (scene.intValue() == 4) {//支付密码
            params.put("user_id", llUserExt.getUserKey());
            params.put("password_scene", "pay_password");
            params.put("amount", amount.toPlainString());
        }
        params.put("flag_chnl", "H5");
        JSONObject result = sendRequest(userInfo.getId(), pgwUrl, LlEnum.PWD_ELEMENT, params);
        pwdElementVO.setToken(result.getString("password_element_token"));

        return pwdElementVO;
    }

    /**
     * DAO密码控件token
     *
     * @return
     */
    public PwdElementVO getDaoPwdElement(Long walletId, String daoUUid, Integer scene, BigDecimal amount) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("encrypt_algorithm", "SM2");
        PwdElementVO pwdElementVO = new PwdElementVO();
        pwdElementVO.setUserId(daoUUid);
        pwdElementVO.setOidPartner(merchantNo);
        params.put("user_id", daoUUid);
        if (scene.intValue() == 1) {//设置密码
            params.put("password_scene", "setting_password");
        } else if (scene.intValue() == 2) {//修改密码
            params.put("password_scene", "change_password");
        } else if (scene.intValue() == 3) {//换绑卡
            params.put("password_scene", "bind_card_password");
        } else if (scene.intValue() == 4) {//提现密码
            if (amount == null || NumberUtil.isLessOrEqual(amount, BigDecimal.ZERO)) {
                throw new GlobalRunTimeException("提现金额不正确");
            }
            params.put("user_id", daoUUid);
            params.put("amount", amount.toPlainString());
            params.put("password_scene", "cashout_password");
            DaoCustomerOpenAccount customer = customerOpenAccountDao.getById(walletId);
            params.put("pyee_name", customer.getBusinessName());
        } else if (scene.intValue() == 5) {//支付密码
            params.put("password_scene", "pay_password");
        }
        params.put("flag_chnl", "PCH5");
        JSONObject result = sendRequest(0L, pgwUrl, LlEnum.PWD_ELEMENT, params);
        pwdElementVO.setToken(result.getString("password_element_token"));

        return pwdElementVO;
    }

    /**
     * 解绑匿名银行卡
     *
     * @return
     */
    public JSONObject unAnonymousBindCard(UserInfo userInfo, String applyNo, UserBankCard userCard) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("user_id", userInfo.getUserUuid());
        params.put("txn_seqno", applyNo);
        params.put("notify_url", unAnonymousBindCardNotify);
        params.put("linked_acctno", LLianPayClient.encrypt(userCard.getBankCardNo()));
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.ANONYMOUS_UN_BIND_CARD, params);
    }


    /**
     * 快捷支付
     *
     * @return
     */
    public JSONObject fastPay(UserInfo userInfo, String goodsName, PayOrder order, UserBankCard userCard) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("txn_seqno", order.getTradeNo());
        params.put("total_amount", order.getPayAmount().toPlainString());
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("user_id", userInfo.getUserUuid());
        params.put("payerInfo", payerInfo);
        JSONObject bankCardInfo = new JSONObject();
        bankCardInfo.put("linked_agrtno", userCard.getSandBid());
        params.put("bankCardInfo", bankCardInfo);
        JSONArray payMethods = new JSONArray();
        JSONObject payMethod = new JSONObject();
        payMethod.put("method", "AGRT_DEBIT_CARD");
        payMethod.put("amount", order.getPayAmount().toPlainString());
        payMethods.add(payMethod);
        params.put("payMethods", payMethods);
        JSONObject riskItem = new JSONObject();
        riskItem.put("frms_ware_category", "4007");
        riskItem.put("user_info_mercht_userno", userInfo.getUserUuid());
        riskItem.put("user_info_bind_phone", userInfo.getUserTel());
        riskItem.put("user_info_dt_register", DateUtil.format(userInfo.getCreateTime(), "yyyyMMddHHmmss"));
        riskItem.put("goods_name", goodsName);
        riskItem.put("user_info_full_name", userCard.getName());
        riskItem.put("user_info_id_type", "0");
        riskItem.put("user_info_id_no", userCard.getIdentityNo());
        riskItem.put("user_info_identify_state", "1");
        riskItem.put("user_info_identify_type", "1");
        riskItem.put("frms_client_chnl", "10");
        riskItem.put("frms_ip_addr", order.getReqIp());
        riskItem.put("user_auth_flag", "1");
        params.put("risk_item", riskItem);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.FAST_PAY, params);

    }

    /**
     * 钱包余额支付
     *
     * @return
     */
    public JSONObject balancePay(UserInfo userInfo, String goodsName, PayOrder order, String password,
                                 LlUserExt llUserExt, IdcardInfo idcardInfo, String randomKey) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
//        params.put("oid_partner",merchantNo);
//        params.put("txn_time", params.getString("timestamp"));
        params.put("txn_seqno", order.getTradeNo());
        params.put("total_amount", order.getPayAmount().toPlainString());
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("user_id", llUserExt.getUserKey());
        payerInfo.put("password", password);
        payerInfo.put("random_key", randomKey);
        params.put("payerInfo", payerInfo);

        JSONObject riskItem = new JSONObject();
        riskItem.put("frms_ware_category", "4007");
        riskItem.put("user_info_mercht_userno", llUserExt.getUserKey());
        riskItem.put("user_info_bind_phone", userInfo.getUserTel());
        riskItem.put("user_info_dt_register", DateUtil.format(userInfo.getCreateTime(), "yyyyMMddHHmmss"));
        riskItem.put("goods_name", goodsName);
        riskItem.put("user_info_full_name", idcardInfo.getName());
        riskItem.put("user_info_id_type", "0");
        riskItem.put("user_info_id_no", idcardInfo.getCardId());
        riskItem.put("user_info_identify_state", "1");
        riskItem.put("user_info_identify_type", "3");
        riskItem.put("frms_client_chnl", "10");
        riskItem.put("frms_ip_addr", order.getReqIp());
        riskItem.put("user_auth_flag", "1");
        params.put("risk_item", riskItem);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.BALANCE_PAY, params);

    }

    public JSONObject fastMallPay(UserInfo userInfo, String goodsName, MallPayOrderRecord order, UserBankCard
            userCard) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("txn_seqno", order.getTradeNo());
        params.put("total_amount", order.getPayAmount().toPlainString());
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("user_id", userInfo.getUserUuid());
        params.put("payerInfo", payerInfo);
        JSONObject bankCardInfo = new JSONObject();
        bankCardInfo.put("linked_agrtno", userCard.getSandBid());
        params.put("bankCardInfo", bankCardInfo);
        JSONArray payMethods = new JSONArray();
        JSONObject payMethod = new JSONObject();
        payMethod.put("method", "AGRT_DEBIT_CARD");
        payMethod.put("amount", order.getPayAmount().toPlainString());
        payMethods.add(payMethod);
        params.put("payMethods", payMethods);
        JSONObject riskItem = new JSONObject();
        riskItem.put("frms_ware_category", "4007");
        riskItem.put("user_info_mercht_userno", userInfo.getUserUuid());
        riskItem.put("user_info_bind_phone", userInfo.getUserTel());
        riskItem.put("user_info_dt_register", DateUtil.format(userInfo.getCreateTime(), "yyyyMMddHHmmss"));
        riskItem.put("goods_name", goodsName);
        riskItem.put("user_info_full_name", userCard.getName());
        riskItem.put("user_info_id_type", "0");
        riskItem.put("user_info_id_no", userCard.getIdentityNo());
        riskItem.put("user_info_identify_state", "1");
        riskItem.put("user_info_identify_type", "1");
        riskItem.put("frms_client_chnl", "10");
        riskItem.put("frms_ip_addr", order.getReqIp());
        riskItem.put("user_auth_flag", "1");
        params.put("risk_item", riskItem);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.FAST_PAY, params);

    }

    /**
     * 验证短信
     *
     * @return
     */
    public void verifySmsCode(UserInfo userInfo, String orderNo, BigDecimal amount, String token, String smsCode,
                              LlUserExt userExt, PayMethodEnum payMethodEnum) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("payer_type", "USER");
        //余额支付需要使用开户时的userKey
        params.put("payer_id", payMethodEnum.equals(LL_BALANCE_PAY) ? userExt.getUserKey() : userInfo.getUserUuid());
        params.put("txn_seqno", orderNo);
        params.put("total_amount", amount.toPlainString());
        params.put("token", token);
        params.put("verify_code", smsCode);
//        log.info("连连支付交易二次确认:{}", JSONObject.toJSONString(params));
        sendRequest(userInfo.getId(), apiUrl, LlEnum.VERIFY_CODE, params);
    }


    /**
     * 查询余额
     *
     * @return
     */
    public JSONObject getBalance(LlUserExt llUserExt) {
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", llUserExt.getUserKey());
        params.put("user_type", "INNERUSER");
        JSONObject result = sendRequest(llUserExt.getUserId(), apiUrl, LlEnum.QUERY_BALANCE, params);
        for (int i = 0; i < result.getJSONArray("acctinfo_list").size(); i++) {
            JSONObject acctinfoList = result.getJSONArray("acctinfo_list").getJSONObject(i);
            if (StrUtil.equals(acctinfoList.getString("acct_type"), "USEROWN_AVAILABLE")) {
                return acctinfoList;
            }
        }
        throw new GlobalRunTimeException("连连支付:未找到可用账户");
    }

    /**
     * 特殊查询余额(因分账实际到账有延迟 所以需要特殊改造查询冻结资金)
     *
     * @return
     */
    public JSONObject getBalanceSpecial(LlUserExt llUserExt) {
//        BalanceVO balanceVO = new BalanceVO();
        JSONObject balance = new JSONObject();
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", llUserExt.getUserKey());
        params.put("user_type", "INNERUSER");
        JSONObject result = sendRequest(llUserExt.getUserId(), apiUrl, LlEnum.QUERY_BALANCE, params);
//        log.info("连连钱包余额查询返回:{}", result.toJSONString());
        for (int i = 0; i < result.getJSONArray("acctinfo_list").size(); i++) {
            JSONObject acctinfoList = result.getJSONArray("acctinfo_list").getJSONObject(i);
            if (StrUtil.equals(acctinfoList.getString("acct_type"), "USEROWN_AVAILABLE")) {
                balance.put("amt_balaval", acctinfoList.getBigDecimal("amt_balaval"));
                balance.put("amt_balfrz", acctinfoList.getBigDecimal("amt_balfrz"));
            }
            if (StrUtil.equals(acctinfoList.getString("acct_type"), "USEROWN_PSETTLE")) {
                balance.put("amt_unsettle", acctinfoList.getBigDecimal("amt_balaval"));
            }
        }
        return balance;
    }

    /**
     * 查询余额变动明细
     *
     * @return
     */
    public String getBalanceDetail(LlUserExt llUserExt, Date startTime, Date endTime, Integer pageNo, Integer pageSize, Integer ioFlag) {
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("date_start", DateUtil.format(startTime, "yyyyMMddHHmmss"));
        params.put("date_end", DateUtil.format(endTime, "yyyyMMddHHmmss"));
        params.put("user_id", llUserExt.getUserKey());
        params.put("user_type", "INNERUSER");
        params.put("acct_type", "USEROWN_AVAILABLE");
        if (null != ioFlag) {
            params.put("flag_dc", ioFlag == 0 ? "CREDIT" : "DEBIT");
        }
        params.put("page_no", pageNo.toString());
        params.put("page_size", pageSize.toString());
        JSONObject result = sendRequest(llUserExt.getUserId(), apiUrl, LlEnum.QUERY_BALANCE_DETAIL, params);
        if (!result.getString("ret_code").equals(SUCCESS_CODE)) {
            throw new GlobalRunTimeException("连连支付:账户变动明细查询失败");
        }
        return result.toJSONString();
    }

    /**
     * 查询DAO余额
     *
     * @return
     */
    public JSONObject getDaoBalance(Long operatorId, String daoUuid) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", daoUuid);
        params.put("user_type", "INNERCOMPANY");
        JSONObject result = sendRequest(operatorId, apiUrl, LlEnum.QUERY_BALANCE, params);
        for (int i = 0; i < result.getJSONArray("acctinfo_list").size(); i++) {
            JSONObject acctinfoList = result.getJSONArray("acctinfo_list").getJSONObject(i);
            if (StrUtil.equals(acctinfoList.getString("acct_type"), "USEROWN_AVAILABLE")) {
                return acctinfoList;
            }
        }
        throw new GlobalRunTimeException("连连支付:未找到可用账户");
    }


    /**
     * 匿名绑卡
     *
     * @param userInfo
     * @param bankBindApply
     * @return
     */
    public JSONObject anonymousBindCard(UserInfo userInfo, BankBindApply bankBindApply) {
        JSONObject params = new JSONObject();
        params.put("user_id", userInfo.getUserUuid());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_time", params.getString("timestamp"));
        params.put("txn_seqno", bankBindApply.getApplyNo());
        params.put("linked_acctno", LLianPayClient.encrypt(bankBindApply.getCardNo()));
        params.put("linked_acctname", LLianPayClient.encrypt(bankBindApply.getName()));
        params.put("linked_phone", LLianPayClient.encrypt(bankBindApply.getPhoneNo()));
        params.put("id_type", "ID_CARD");
        params.put("notify_url", anonymousBindCardNotify);
        params.put("id_no", LLianPayClient.encrypt(bankBindApply.getCertificateNo()));
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.ANONYMOUS_BIND_CARD_APPLY, params);
    }

    /**
     * 找回密码
     *
     * @param userInfo
     * @return
     */
    public JSONObject findPwd(UserInfo userInfo, String bankCard) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        UserBankCard firstCard = userBankCardDao.getFirstCard(userInfo.getId(), PayChannelEnum.LL_PAY);
        JSONObject params = new JSONObject();
        params.put("user_id", llUserExt.getUserKey());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("linked_acctno", bankCard);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.FIND_PASSWORD, params);
    }


    /**
     * dao找回密码
     *
     * @return
     */
    public JSONObject daoFindPwd(Long operatorId, String daoUuid) {
        JSONObject params = new JSONObject();
        params.put("user_id", daoUuid);
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        return sendRequest(operatorId, apiUrl, LlEnum.FIND_PASSWORD, params);
    }

    /**
     * dao密码验证
     *
     * @return
     */
    public JSONObject daoPwdVerify(Long operatorId, String daoUUid, String token, String smsCode, String
            randomKey, String password) {
        JSONObject params = new JSONObject();
        params.put("user_id", daoUUid);
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("token", token);
        params.put("verify_code", smsCode);
        params.put("random_key", randomKey);
        params.put("password", password);
        return sendRequest(operatorId, apiUrl, LlEnum.PASSWORD_VERIFY, params);
    }

    /**
     * 提现结果查询
     *
     * @return
     */
    public JSONObject findWithdrawResult(String orderNo) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_seqno", orderNo);
        return sendRequest(0L, apiUrl, LlEnum.FIND_WITHDRAW_RESULT, params);
    }


    /**
     * 验证短信
     *
     * @return
     */
    public void withdrawVerifySmsCode(UserInfo userInfo, SandWithdrawRecord withdrawRecord, String smsCode) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("payer_type", "USER");
        params.put("payer_id", llUserExt.getUserKey());
        params.put("txn_seqno", withdrawRecord.getCustomerOrderNo());
        params.put("total_amount", withdrawRecord.getAmount().toPlainString());
        params.put("token", withdrawRecord.getLlToken());
        params.put("verify_code", smsCode);
        sendRequest(userInfo.getId(), apiUrl, LlEnum.VERIFY_CODE, params);
    }

    /**
     * dao提现验证短信
     *
     * @return
     */
    public void daoWithdrawVerifySmsCode(Long operatorId, String daoUuid, DaoWithdrawRecord withdrawRecord, String smsCode) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("payer_type", "USER");
        params.put("payer_id", daoUuid);
        params.put("txn_seqno", withdrawRecord.getCustomerOrderNo());
        params.put("total_amount", withdrawRecord.getAmount().toPlainString());
        params.put("token", withdrawRecord.getLlToken());
        params.put("verify_code", smsCode);
        sendRequest(operatorId, apiUrl, LlEnum.VERIFY_CODE, params);
    }


    /**
     * 密码验证
     *
     * @param userInfo
     * @return
     */
    public JSONObject pwdVerify(UserInfo userInfo, String token, String smsCode, String randomKey, String password) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        JSONObject params = new JSONObject();
        params.put("user_id", llUserExt.getUserKey());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("token", token);
        params.put("verify_code", smsCode);
        params.put("random_key", randomKey);
        params.put("password", password);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.PASSWORD_VERIFY, params);
    }


    /**
     * B端开户
     *
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public JSONObject businessOpenAccount(DaoCustomerOpenAccount customerOpenAccount, DaoAccountLegalPerson
            legalPerson, DaoAccountBankInfo bankInfo, String password, String randomKey) {
        JSONObject params = new JSONObject();
        params.put("user_id", customerOpenAccount.getDaoUuid());
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_seqno", customerOpenAccount.getSeqNo());
        params.put("txn_time", params.get("timestamp"));
        params.put("notify_url", businessOpenAccountNotifyUrl);
        JSONObject basicInfo = new JSONObject();
        basicInfo.put("reg_phone", customerOpenAccount.getRegPhone());
        basicInfo.put("user_name", customerOpenAccount.getBusinessName());
        basicInfo.put("id_type", "UNIFIED_SOCIAL_CREDIT_CODE");
        basicInfo.put("id_no", customerOpenAccount.getBusinessLicenseCode());
        basicInfo.put("id_exp", DateUtil.format(customerOpenAccount.getExpDate(), "yyyyMMdd"));
        basicInfo.put("address", customerOpenAccount.getAddress());
        basicInfo.put("reg_email", customerOpenAccount.getRegMail());
        basicInfo.put("password", password);
        basicInfo.put("random_key", randomKey);
        basicInfo.put("unified_code", upLoadFile(customerOpenAccount.getOperatorId(), customerOpenAccount.getDaoUuid(), LlUploadFileTypeEnum.USER_IMAGE, customerOpenAccount.getBusinessLicenseImage()));
        params.put("basicInfo", basicInfo);
        JSONObject linkedAcctInfo = new JSONObject();
        linkedAcctInfo.put("linked_acctno", bankInfo.getBankAccount());
        linkedAcctInfo.put("linked_bankcode", bankInfo.getBankCode());
        linkedAcctInfo.put("linked_brbankno", bankInfo.getBrBankCode());
        linkedAcctInfo.put("linked_acctname", customerOpenAccount.getBusinessName());
        linkedAcctInfo.put("linked_phone", bankInfo.getPhone());
        params.put("linkedAcctInfo", linkedAcctInfo);
        JSONObject legalreptInfo = new JSONObject();
        legalreptInfo.put("legalrept_name", legalPerson.getLegalPersonName());
        legalreptInfo.put("legalrept_phone", legalPerson.getLegalPersonPhone());
        legalreptInfo.put("legalrept_idno", legalPerson.getLegalPersonIdCard());
        legalreptInfo.put("id_emblem", upLoadFile(customerOpenAccount.getOperatorId(), customerOpenAccount.getDaoUuid(), LlUploadFileTypeEnum.USER_IMAGE, legalPerson.getLegalPersonEmblem()));
        legalreptInfo.put("id_portrait", upLoadFile(customerOpenAccount.getOperatorId(), customerOpenAccount.getDaoUuid(), LlUploadFileTypeEnum.USER_IMAGE, legalPerson.getLegalPersonPortrait()));
        legalreptInfo.put("legalrept_idexp", DateUtil.format(legalPerson.getLegalPersonExp(), "yyyyMMdd"));
        params.put("legalreptInfo", legalreptInfo);
        JSONObject contactsInfo = new JSONObject();
        contactsInfo.put("contacts_name", customerOpenAccount.getContactsName());
        contactsInfo.put("contacts_phone", customerOpenAccount.getContactsPhone());
        params.put("contactsInfo", contactsInfo);
        JSONObject basicAcctInfo = new JSONObject();
        basicAcctInfo.put("basicacct_bankcode", bankInfo.getBankCode());
        basicAcctInfo.put("basicacct_no", bankInfo.getBankAccount());
        params.put("basicAcctInfo", basicAcctInfo);
        JSONObject result = sendRequest(customerOpenAccount.getOperatorId(), apiUrl, LlEnum.BUSINESS_OPEN, params);
        return result;
    }


    public void regPhoneApply(Long operatorId, String daoUuid, String phone) {
        JSONObject params = new JSONObject();
        params.put("user_id", daoUuid);
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("reg_phone", phone);
        sendRequest(operatorId, apiUrl, LlEnum.REGPHONE_VERIFYCODE_APPLY, params);
    }

    public void regPhoneVerify(Long operatorId, String daoUuid, String phone, String verifyCode) {
        JSONObject params = new JSONObject();
        params.put("user_id", daoUuid);
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("reg_phone", phone);
        params.put("verify_code", verifyCode);
        sendRequest(operatorId, apiUrl, LlEnum.REGPHONE_VERIFYCODE_VERIFY, params);
    }


    public void openAccountVerify(Long operatorId, String daoUuid, String seqNo, String token, String verifyCode) {
        JSONObject params = new JSONObject();
        params.put("user_id", daoUuid);
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_seqno", seqNo);
        params.put("token", token);
        params.put("verify_code", verifyCode);
        sendRequest(operatorId, apiUrl, LlEnum.BUSINESS_OPEN_VERIFY, params);
    }

    public String upLoadFile(Long operatorId, String daoUuid, LlUploadFileTypeEnum type, String imageUrl) {
        JSONObject params = new JSONObject();
        params.put("user_id", daoUuid);
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("txn_seqno", UUID.fastUUID().toString().replaceAll("-", ""));
        params.put("txn_time", params.get("timestamp"));
        params.put("context_type", type.getCode());
        ImageDTO imageDTO = getImageBse64WithUrl(imageUrl);
        params.put("file_type", imageDTO.getType());
        params.put("file_context", imageDTO.getBase64());
        JSONObject result = sendRequest(operatorId, fileUrl, LlEnum.FILE_UPLOAD, params);

        return result.getString("doc_id");
    }

    /**
     * 提现确认
     *
     * @param sandWithdrawRecord
     */
    public void withdrawConfirm(SandWithdrawRecord sandWithdrawRecord, boolean approvalStatus, String remark) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("notify_url", withdrawNotify);
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", sandWithdrawRecord.getCustomerOrderNo());
        orderInfo.put("total_amount", sandWithdrawRecord.getAmount().toPlainString());
        orderInfo.put("fee_amount", sandWithdrawRecord.getFeeAmount().toPlainString());
        params.put("orderInfo", orderInfo);
        JSONObject checkInfo = new JSONObject();
        checkInfo.put("check_result", approvalStatus ? "ACCEPT" : "CANCEL");
        params.put("checkInfo", checkInfo);
        try {
            JSONObject jsonObject = sendRequest(sandWithdrawRecord.getUserId(), apiUrl, LlEnum.WITHDRAW_CHECK, params);
        } catch (GlobalRunTimeException e) {
            log.warn("连连查询失败:", e);
        }
        sandWithdrawRecord.setRemark(remark);
        sandWithdrawRecord.setConfirmStatus(true);
        sandWithdrawRecord.updateById();
    }

    /**
     * 用户资金转入公司
     */
    public JSONObject transferTmp(String userNo, String amount) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("directionalpay_flag", "Y");
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", OrderNoUtil.getOrderNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", amount);
        orderInfo.put("txn_purpose", "资金退回");
        params.put("orderInfo", orderInfo);
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("payer_type", "USER");
        payerInfo.put("payer_id", userNo);
        payerInfo.put("payer_accttype", "USEROWN");
        params.put("payerInfo", payerInfo);
        JSONObject payeeInfo = new JSONObject();
        payeeInfo.put("payee_type", "MERCHANT");
        payeeInfo.put("payee_id", merchantNo);
        payeeInfo.put("payee_accttype", "MCHOWN");
        payeeInfo.put("payee_amount", amount);
        params.put("payeeInfo", payeeInfo);
        return sendRequest(0L, apiUrl, LlEnum.TRANSFER, params);
    }

    /**
     * 提现申请
     *
     * @param userInfo
     * @return
     */
    public Long withdraw(UserInfo userInfo, LlUserExt llUserExt, WithdrawBankCard withdrawBankCard, BigDecimal
            amount, String password, String randomKey) {
        BigDecimal balance = getBalance(llUserExt).getBigDecimal("amt_balaval");
        if (NumberUtil.isLess(balance, amount)) {
            throw new GlobalRunTimeException("余额不足");
        }
        SandWithdrawRecord withdrawRecord = new SandWithdrawRecord();
        withdrawRecord.setUserId(llUserExt.getUserId());
        withdrawRecord.setCustomerOrderNo(OrderNoUtil.getOrderNo());
        withdrawRecord.setAmount(amount);
        String fee = staticDataDao.getByType("ll_withdrawal_fee").getValue();
        String minimumWithdrawalFee = staticDataDao.getByType("minimum_withdrawal_fee").getValue();
        BigDecimal feeAmount = amount.multiply(new BigDecimal(fee)).setScale(2, RoundingMode.FLOOR);
        feeAmount = feeAmount.compareTo(Convert.toBigDecimal(minimumWithdrawalFee)) > 0 ? feeAmount : Convert.toBigDecimal(minimumWithdrawalFee);
        withdrawRecord.setFeeAmount(feeAmount);
        withdrawRecord.setRealAmount(amount.subtract(withdrawRecord.getFeeAmount()));
        withdrawRecord.setChannel(WalletChannelEnum.LL);
        withdrawRecord.setSettleTime(DateUtil.tomorrow());
        withdrawRecord.setConfirmStatus(false);
        withdrawRecord.setRelatedCardNo(withdrawBankCard.getRelatedCardNo());
        withdrawRecord.setStatus(0);
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("notify_url", withdrawNotify);
        params.put("check_flag", "Y");
        JSONObject riskItem = new JSONObject();
        riskItem.put("frms_ware_category", "4007");
        riskItem.put("user_info_mercht_userno", llUserExt.getUserKey());
        riskItem.put("user_info_bind_phone", userInfo.getUserTel());
        riskItem.put("user_info_dt_register", DateUtil.format(userInfo.getCreateTime(), "yyyyMMddHHmmss"));
        riskItem.put("goods_name", "用户提现");
        params.put("risk_item", riskItem);
        params.put("linked_agrtno", withdrawRecord.getRelatedCardNo());
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", withdrawRecord.getCustomerOrderNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", withdrawRecord.getAmount().toPlainString());
        orderInfo.put("fee_amount", withdrawRecord.getFeeAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
        if (NumberUtil.isGreater(amount, BigDecimal.valueOf(50000))) {
            orderInfo.put("postscript", "用户提现");
        }
        params.put("orderInfo", orderInfo);
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("payer_type", "USER");
        payerInfo.put("payer_id", llUserExt.getUserKey());
        payerInfo.put("password", password);
        payerInfo.put("random_key", randomKey);
        params.put("payerInfo", payerInfo);
        JSONObject jsonObject = sendRequest(userInfo.getId(), apiUrl, LlEnum.WITHDRAW_APPLY, params);
        withdrawRecord.setLlToken(jsonObject.getString("token"));
        withdrawRecord.insert();
        return withdrawRecord.getId();
    }


    /**
     * DAO提现申请
     *
     * @return
     */
    public Long daoWithdraw(DaoCustomerOpenAccount customerOpenAccount, Long operatorId, DaoAccountBankInfo
            daoAccountBankInfo, BigDecimal amount, String password, String randomKey) {
        BigDecimal balance = getDaoBalance(operatorId, customerOpenAccount.getDaoUuid()).getBigDecimal("amt_balaval");
        if (NumberUtil.isLess(balance, amount)) {
            throw new GlobalRunTimeException("余额不足");
        }
        DaoWithdrawRecord withdrawRecord = new DaoWithdrawRecord();
        withdrawRecord.setDaoId(customerOpenAccount.getDaoId());
        withdrawRecord.setWalletId(customerOpenAccount.getId());
        withdrawRecord.setBankAccountId(daoAccountBankInfo.getId());
        withdrawRecord.setOperatorId(operatorId);
        withdrawRecord.setCustomerOrderNo(OrderNoUtil.getOrderNo());
        withdrawRecord.setAmount(amount);
        String supplyIgnoreFee = staticDataDao.getByType("supply_ignore_fee").getValue();
        JSONArray array = JSONArray.parseArray(supplyIgnoreFee);
        if (array.contains(customerOpenAccount.getDaoId())) {
            withdrawRecord.setFeeAmount(BigDecimal.ZERO);
        } else {
            String fee = staticDataDao.getByType("dao_withdrawal_fee").getValue();
            withdrawRecord.setFeeAmount(new BigDecimal(fee));
        }
        withdrawRecord.setRealAmount(amount.subtract(withdrawRecord.getFeeAmount()));
        withdrawRecord.setChannel(WalletChannelEnum.LL);
        withdrawRecord.setRelatedCardNo(daoAccountBankInfo.getAgrtNo());
        withdrawRecord.setStatus(0);
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("notify_url", daoWithdrawNotify);
        JSONObject riskItem = new JSONObject();
        riskItem.put("frms_ware_category", "4007");
        riskItem.put("user_info_mercht_userno", customerOpenAccount.getDaoUuid());
        riskItem.put("user_info_bind_phone", customerOpenAccount.getRegPhone());
        riskItem.put("user_info_dt_register", DateUtil.format(customerOpenAccount.getCreateTime(), "yyyyMMddHHmmss"));
        riskItem.put("goods_name", "商家货款结算");
        params.put("risk_item", riskItem);
        params.put("linked_agrtno", withdrawRecord.getRelatedCardNo());
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", withdrawRecord.getCustomerOrderNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", withdrawRecord.getAmount().toPlainString());
        if (NumberUtil.isGreater(withdrawRecord.getFeeAmount(), BigDecimal.ZERO)) {
            orderInfo.put("fee_amount", withdrawRecord.getFeeAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
        }
        if (NumberUtil.isGreater(amount, BigDecimal.valueOf(50000))) {
            orderInfo.put("postscript", "商家货款结算");
        }

        params.put("orderInfo", orderInfo);
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("payer_type", "USER");
        payerInfo.put("payer_id", customerOpenAccount.getDaoUuid());
        payerInfo.put("password", password);
        payerInfo.put("random_key", randomKey);
        params.put("payerInfo", payerInfo);
        JSONObject jsonObject = sendRequest(operatorId, apiUrl, LlEnum.WITHDRAW_APPLY, params);
        withdrawRecord.setLlToken(jsonObject.getString("token"));
        withdrawRecord.insert();
        return withdrawRecord.getId();
    }

    private JSONObject sendRequest(Long userId, String requestUrl, LlEnum llEnum, JSONObject params) {

        params.put("oid_partner", merchantNo);

        SandBizRecord sandBizRecord = new SandBizRecord();
        sandBizRecord.setUserId(userId);
        if (llEnum == LlEnum.CREATE_ORDER) {
            sandBizRecord.setCustomerOrderNo(params.getJSONObject("orderInfo").getString("txn_seqno"));
        } else {
            sandBizRecord.setCustomerOrderNo(StrUtil.isNotBlank(params.getString("txn_seqno")) ? params.getString("txn_seqno") : "0");
        }
        sandBizRecord.setBizMethod(llEnum.getMethod());
        sandBizRecord.setMethodDesc(llEnum.getDesc());
        if (llEnum != LlEnum.FILE_UPLOAD) {
            sandBizRecord.setReqParams(JSONObject.toJSONString(params));
        }
        JSONObject result = JSONObject.parseObject(LLianPayClient.sendRequest(requestUrl, sandBizRecord.getBizMethod(), JSON.toJSONString(params)));
        sandBizRecord.setResult(result.toJSONString());
        sandBizRecord.insert();
        if (llEnum == LlEnum.FAST_PAY || llEnum == LlEnum.WITHDRAW_APPLY || llEnum == LlEnum.BALANCE_PAY) {
            if (StrUtil.equals(result.getString("ret_code"), "8888")) {
                return result;
            } else {
                throw new GlobalRunTimeException("连连调用失败:" + result.getString("ret_msg"));
            }
        } else if (llEnum == LlEnum.VERIFY_CODE) {
            if (StrUtil.equals(result.getString("ret_code"), "8889") || StrUtil.equals(result.getString("ret_code"), SUCCESS_CODE)) {
                return result;
            } else {
                throw new GlobalRunTimeException("连连调用失败:" + result.getString("ret_msg"));
            }
        } else {
            if (StrUtil.equals(result.getString("ret_code"), SUCCESS_CODE)) {
                return result;
            } else {
                throw new GlobalRunTimeException("连连调用失败:" + result.getString("ret_msg"));
            }
        }

    }

    /**
     * 分账专用避免重复分账不抛异常
     *
     * @param userId
     * @param requestUrl
     * @param llEnum
     * @param params
     * @return
     */
    private JSONObject sendSplitRequest(Long userId, String requestUrl, LlEnum llEnum, JSONObject params) {

        params.put("oid_partner", merchantNo);

        SandBizRecord sandBizRecord = new SandBizRecord();
        sandBizRecord.setUserId(userId);
        if (llEnum == LlEnum.CREATE_ORDER) {
            sandBizRecord.setCustomerOrderNo(params.getJSONObject("orderInfo").getString("txn_seqno"));
        } else {
            sandBizRecord.setCustomerOrderNo(StrUtil.isNotBlank(params.getString("txn_seqno")) ? params.getString("txn_seqno") : "0");
        }
        sandBizRecord.setBizMethod(llEnum.getMethod());
        sandBizRecord.setMethodDesc(llEnum.getDesc());
        if (llEnum != LlEnum.FILE_UPLOAD) {
            sandBizRecord.setReqParams(JSONObject.toJSONString(params));
        }
        JSONObject result = JSONObject.parseObject(LLianPayClient.sendRequest(requestUrl, sandBizRecord.getBizMethod(), JSON.toJSONString(params)));
        sandBizRecord.setResult(result.toJSONString());
        sandBizRecord.insert();
//        if (llEnum == LlEnum.FAST_PAY || llEnum == LlEnum.WITHDRAW_APPLY) {
//            if (StrUtil.equals(result.getString("ret_code"), "8888")) {
//                return result;
//            } else {
//                throw new GlobalRunTimeException("连连调用失败:" + result.getString("ret_msg"));
//            }
//        } else if (llEnum == LlEnum.VERIFY_CODE) {
//            if (StrUtil.equals(result.getString("ret_code"), "8889") || StrUtil.equals(result.getString("ret_code"), SUCCESS_CODE)) {
//                return result;
//            } else {
//                throw new GlobalRunTimeException("连连调用失败:" + result.getString("ret_msg"));
//            }
//        } else {
//            if (StrUtil.equals(result.getString("ret_code"), SUCCESS_CODE)) {
//                return result;
//            } else {
//                throw new GlobalRunTimeException("连连调用失败:" + result.getString("ret_msg"));
//            }
//        }
        return result;

    }


    /**
     * 退款refund
     *
     * @param userInfo
     * @return
     */
    public JSONObject refund(UserInfo userInfo, String originOrderNo, String refundTradeNo, String amount, String notifyUrl,PayOrder payOrder) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        if(payOrder.getPayType().equals(PayMethodEnum.LL_BALANCE_PAY)){
            LlUserExt llUserExt = llUserExtService.getValidByUserId(userInfo.getId());
            if(ObjectUtil.isNull(llUserExt)){
                throw new  GlobalRunTimeException("用户连连开户信息不存在,请检查!");
            }
            params.put("user_id", llUserExt.getUserKey());
        }else {
            params.put("user_id", userInfo.getUserUuid());
        }

        if (StrUtil.isNotBlank(notifyUrl)) {
            params.put("notifyUrl", notifyUrl);
        }
        JSONObject originalOrderInfo = new JSONObject();
        originalOrderInfo.put("txn_seqno", originOrderNo);
        originalOrderInfo.put("total_amount", amount);
        params.put("originalOrderInfo", originalOrderInfo);
        JSONObject refundOrderInfo = new JSONObject();
        refundOrderInfo.put("refund_seqno", refundTradeNo);
        refundOrderInfo.put("refund_time", params.get("timestamp"));
        refundOrderInfo.put("refund_amount", amount);
        params.put("refundOrderInfo", refundOrderInfo);
        JSONObject pyeeRefundInfos = new JSONObject();
        pyeeRefundInfos.put("payee_type", "MERCHANT");
        pyeeRefundInfos.put("payee_id", merchantNo);
//        pyeeRefundInfos.put("payee_accttype", "MCHOWN");
        //连连支付现在是担保支付这里要传平台担保户
        pyeeRefundInfos.put("payee_accttype", "MCHASSURE");
        pyeeRefundInfos.put("payee_refund_amount", amount);
        params.put("pyeeRefundInfos", pyeeRefundInfos);
        JSONObject refundMethods = new JSONObject();
        //区分付款方使用的付款方式
        if(payOrder.getPayType().equals(PayMethodEnum.LL_BALANCE_PAY)){
            refundMethods.put("method", "BALANCE");
        }else{
            refundMethods.put("method", "AGRT_DEBIT_CARD");
        }

        refundMethods.put("amount", amount);
        params.put("refundMethods", refundMethods);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.REFUND, params);
    }


    /**
     * 退款refund
     *
     * @param userInfo
     * @return
     */
    public JSONObject refundMall(UserInfo userInfo, String originOrderNo, String refundTradeNo, String amount, String notifyUrl) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", userInfo.getUserUuid());
        if (StrUtil.isNotBlank(notifyUrl)) {
            params.put("notifyUrl", notifyUrl);
        }
        JSONObject originalOrderInfo = new JSONObject();
        originalOrderInfo.put("txn_seqno", originOrderNo);
        originalOrderInfo.put("total_amount", amount);
        params.put("originalOrderInfo", originalOrderInfo);
        JSONObject refundOrderInfo = new JSONObject();
        refundOrderInfo.put("refund_seqno", refundTradeNo);
        refundOrderInfo.put("refund_time", params.get("timestamp"));
        refundOrderInfo.put("refund_amount", amount);
        params.put("refundOrderInfo", refundOrderInfo);
        JSONObject pyeeRefundInfos = new JSONObject();
        pyeeRefundInfos.put("payee_type", "MERCHANT");
        pyeeRefundInfos.put("payee_id", merchantNo);
        pyeeRefundInfos.put("payee_accttype", "MCHOWN");
        //连连支付现在是担保支付这里要传平台担保户
//        pyeeRefundInfos.put("payee_accttype", "MCHASSURE");
        pyeeRefundInfos.put("payee_refund_amount", amount);
        params.put("pyeeRefundInfos", pyeeRefundInfos);
        JSONObject refundMethods = new JSONObject();
        refundMethods.put("method", "AGRT_DEBIT_CARD");
        refundMethods.put("amount", amount);
        params.put("refundMethods", refundMethods);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.REFUND, params);
    }


    /**
     * 资金流水
     *
     * @return
     */
    public JSONObject transactionFlow(Long operatorId, String uuid, Integer dcFlag, Date startTime, Date
            EndTime, Page page) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", uuid);
        params.put("user_type", "INNERCOMPANY");
        params.put("acct_type", "USEROWN_AVAILABLE");
        params.put("date_start", DateUtil.format(startTime, "yyyyMMddHHmmss"));
        params.put("date_end", DateUtil.format(EndTime, "yyyyMMddHHmmss"));
        if (dcFlag != null) {
            if (dcFlag.intValue() == 1) {
                params.put("flag_dc", "DEBIT");
            } else if (dcFlag.intValue() == 2) {
                params.put("flag_dc", "CREDIT");
            }
        }
        params.put("page_no", page.getCurrent());
        params.put("page_size", page.getSize());
        return sendRequest(operatorId, apiUrl, LlEnum.QUERY_ACCTSERIAL, params);
    }


    /**
     * 佣金代发
     *
     * @param userInfo
     * @param sandTransferRecord
     * @return
     */
    public JSONObject transfer(UserInfo userInfo, SandTransferRecord sandTransferRecord) {
        LlUserExt llUserExt = llUserExtService.getByUserId(userInfo.getId());
        Assert.isTrue(ObjectUtil.isNotNull(llUserExt) && llUserExt.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("连连支付尚未开户"));
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
//        params.put("notify_url", LlConfig.transferNotify);
        JSONObject riskItem = new JSONObject();
        riskItem.put("frms_ware_category", "4007");
        riskItem.put("user_info_mercht_userno", userInfo.getUserUuid());
        riskItem.put("user_info_bind_phone", userInfo.getUserTel());
        riskItem.put("user_info_dt_register", DateUtil.format(userInfo.getCreateTime(), "yyyyMMddHHmmss"));
        riskItem.put("goods_name", "佣金代发");
        params.put("risk_item", riskItem);
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", sandTransferRecord.getCustomerOrderNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", sandTransferRecord.getAmount().toPlainString());
        orderInfo.put("txn_purpose", "佣金支付");
        params.put("orderInfo", orderInfo);
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("payer_type", "MERCHANT");
        payerInfo.put("payer_id", merchantNo);
        payerInfo.put("payer_accttype", "MCHOWN");
        params.put("payerInfo", payerInfo);
        JSONObject payeeInfo = new JSONObject();
        payeeInfo.put("payee_type", "USER");
        payeeInfo.put("payee_id", llUserExt.getUserKey());
        payeeInfo.put("payee_accttype", "USEROWN");
        payeeInfo.put("payee_amount", sandTransferRecord.getAmount().toPlainString());
        params.put("payeeInfo", payeeInfo);
        return sendRequest(userInfo.getId(), apiUrl, LlEnum.TRANSFER, params);
    }

    /**
     * 转账给DAO
     *
     * @param userCreatorInfo
     * @return
     */
    public JSONObject daoTransfer(UserCreatorInfo userCreatorInfo, DaoTransfer daoTransfer) {
        DaoCustomerOpenAccount account = customerOpenAccountDao.getById(daoTransfer.getSourceId());
        if (ObjectUtil.isNull(account) || account.getStatus() != AccountStatusEnum.SUCCESS) {
            throw new GlobalRunTimeException("连连开户未完成");
        }
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        JSONObject riskItem = new JSONObject();
        riskItem.put("frms_ware_category", "4007");
        riskItem.put("user_info_mercht_userno", userCreatorInfo.getDaoUuid());
        riskItem.put("user_info_bind_phone", account.getRegPhone());
        riskItem.put("user_info_dt_register", DateUtil.format(userCreatorInfo.getCreateTime(), "yyyyMMddHHmmss"));
        riskItem.put("goods_name", "货款结算");
        params.put("risk_item", riskItem);
        JSONObject orderInfo = new JSONObject();
        orderInfo.put("txn_seqno", daoTransfer.getTradeNo());
        orderInfo.put("txn_time", params.getString("timestamp"));
        orderInfo.put("total_amount", daoTransfer.getAmount().toPlainString());
        orderInfo.put("txn_purpose", "货款结算");
        if (NumberUtil.isGreaterOrEqual(daoTransfer.getAmount(), BigDecimal.valueOf(50000))) {
            orderInfo.put("postscript", "商品货款分账");
        }
        params.put("orderInfo", orderInfo);
        JSONObject payerInfo = new JSONObject();
        payerInfo.put("payer_type", "MERCHANT");
        payerInfo.put("payer_id", merchantNo);
        payerInfo.put("payer_accttype", "MCHOWN");
        params.put("payerInfo", payerInfo);
        JSONObject payeeInfo = new JSONObject();
        payeeInfo.put("payee_type", "USER");
        payeeInfo.put("payee_id", account.getDaoUuid());
        payeeInfo.put("payer_accttype", "USEROWN");
        payeeInfo.put("payee_amount", daoTransfer.getAmount().toPlainString());
        params.put("payeeInfo", payeeInfo);
        return sendRequest(userCreatorInfo.getUserId(), apiUrl, LlEnum.TRANSFER, params);
    }

    /**
     * 修改个人信息
     *
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public JSONObject modifyUserInfo(Long userId, String expDate, String stdDate, String emblemId, String emblemImage, String portaitId, String portaitImage, String authroityName, String address) {
        LlUserExt userExt = llUserExtService.getByUserId(userId);
        if (ObjectUtil.isNull(userExt) || userExt.getStatus() != AccountStatusEnum.SUCCESS) {
            throw new GlobalRunTimeException("请先完成连连开户");
        }
        LlModifyUserInfo modifyUserInfo = new LlModifyUserInfo();
        modifyUserInfo.setUserId(userId);
        modifyUserInfo.setSeqNo(OrderNoUtil.getOrderNo());
        modifyUserInfo.setTxnTime(DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        modifyUserInfo.setIdExp(expDate);
        modifyUserInfo.setIdStd(stdDate);
        modifyUserInfo.setEmblemImage(emblemImage);
        modifyUserInfo.setEmblemId(emblemId);
        modifyUserInfo.setPortraitId(portaitId);
        modifyUserInfo.setPortraitImage(portaitImage);
        modifyUserInfo.setAuthorityName(authroityName);
        modifyUserInfo.setAddress(address);
        modifyUserInfo.setStatus(AccountStatusEnum.OPENING);
        modifyUserInfo.insert();
        JSONObject params = new JSONObject();
        params.put("timestamp", modifyUserInfo.getTxnTime());
        params.put("txn_time", modifyUserInfo.getTxnTime());
        params.put("txn_seqno", modifyUserInfo.getSeqNo());
        params.put("user_id", userExt.getUserKey());
        params.put("update_info", "1");
        params.put("notify_url", modifyUserNotifyUrl);
        JSONObject basicInfo = new JSONObject();
        basicInfo.put("id_exp", modifyUserInfo.getIdExp());
        basicInfo.put("id_std", modifyUserInfo.getIdStd());
        basicInfo.put("id_emblem", modifyUserInfo.getEmblemId());
        basicInfo.put("id_portrait", modifyUserInfo.getPortraitId());
        basicInfo.put("id_authority", modifyUserInfo.getAuthorityName());
        basicInfo.put("address", modifyUserInfo.getAddress());
        params.put("basicInfo", basicInfo);
        return sendRequest(0L, apiUrl, LlEnum.MODIFY_USERINFO, params);
    }

    /**
     * 查询用户信息
     *
     * @return
     */
    public JSONObject queryUserInfo(Long userId, String userKey) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", userKey);
        return sendRequest(userId, apiUrl, LlEnum.QUERY_USERINFO, params);
    }

    /**
     * 更新用户等级
     *
     * @return
     */
    public JSONObject updateUserLevel(Long userId, String userKey) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", userKey);
        params.put("txn_seqno", OrderNoUtil.getOrderNo());
        params.put("txn_time", params.getString("timestamp"));
        JSONObject accountInfo = new JSONObject();
        accountInfo.put("account_type", "PERSONAL_PAYMENT_ACCOUNT");
        accountInfo.put("account_need_level", "V3");
        params.put("accountInfo", accountInfo);
        return sendRequest(userId, apiUrl, LlEnum.UPDATE_USER_LEVEL, params);
    }

    public JSONObject queryLinked(String userKey) {
        JSONObject params = new JSONObject();
        params.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        params.put("user_id", userKey);
        return sendRequest(0L, apiUrl, LlEnum.QUERY_LINKED, params);
    }


    public JSONObject largeLineNumberQuery(JSONObject jsonObject) {
        jsonObject.put("timestamp", DateUtil.format(DateTime.now(), "yyyyMMddHHmmss"));
        return sendRequest(0L, apiUrl, LlEnum.LARGE_LINE_NUMBER_QUERY, jsonObject);
    }

    private final static Map<String, String> bankMapping = new HashMap<String, String>() {{
        put("01030000", "中国农业银行");
        put("04202220", "大连银行（大连市商业银行）");
        put("01050000", "中国建设银行");
        put("04145210", "汉口银行（武汉市商业银行）");
        put("25260344", "AEON信贷财务亚洲有限公司");
        put("14404900", "河南省农村信用社联合社");
        put("14505800", "广东省农村信用社联合社");
        put("03320000", "南洋商业银行");
        put("05755200", "湖北银行（襄樊市商业银行股份有限公司）");
        put("03220000", "渣打银行香港有限公司");
        put("03200000", "东亚银行中国有限公司");
        put("05332740", "七台河市城市信用社");
        put("05284630", "泰安银行（泰安市商业银行）");
        put("03260000", "恒生银行");
        put("15566152", "广西鹿寨渝农商村镇银行");
        put("14023052", "昆山农信社");
        put("15277470", "普洱民生村镇银行");
        put("64094510", "齐鲁银行（济南市商业银行）");
        put("04562230", "鞍山银行（鞍山市商业银行）");
        put("04263380", "金华银行股份有限公司（金华市商业银行）");
        put("04453020", "无锡市商业银行");
        put("47980344", "中国银行香港有限公司");
        put("14113030", "徐州市市郊农村信用合作社");
        put("04803070", "连云港市商业银行");
        put("04115010", "焦作中旅银行（焦作市商业银行）");
        put("15214213", "安义融兴村镇银行");
        put("15433613", "安徽肥西石银村镇银行");
        put("15736610", "广元包商贵民村镇银行");
        put("15003363", "安吉交银村镇银行");
        put("15195377", "松滋中银富登村镇银行");
        put("15402220", "大连保税区珠江村镇银行");
        put("14012900", "上海农信");
        put("04943030", "徐州市商业银行");
        put("04392270", "锦州银行股份有限公司（锦州市商业银行）");
        put("14385500", "湖南省农村信用社联合社");
        put("15136900", "重庆农村商业银行");
        put("03320000", "南洋商业银行（中国）");
        put("03330001", "法国兴业银行（中国）");
        put("27090392", "日本三菱信用卡公司");
        put("01020344", "中国工商银行(亚洲)有限公司");
        put("14498500", "青海省农村信用社联合社");
        put("15272929", "嘉定民生村镇银行");
        put("29470608", "PVBCardCorporation");
        put("14144520", "青岛农信");
        put("05722280", "营口沿海银行");
        put("05803320", "宁波通商银行");
        put("28790784", "CommercialBankofDubai");
        put("15033161", "兴化苏南村镇银行");
        put("15142050", "鄂尔多斯市东胜蒙银村镇银行");
        put("15214933", "新安融兴村镇银行");
        put("15301750", "晋中市榆次融信村镇银行");
        put("15584510", "济南长清沪农商村镇银行");
        put("15584630", "泰安沪农商村镇银行");
        put("15584631", "宁阳沪农商村镇银行");
        put("15584633", "东平沪农商村镇银行");
        put("15585525", "醴陵沪农商村镇银行");
        put("15585624", "双峰沪农商村镇银行");
        put("01020360", "中国工商银行印尼分行");
        put("04462269", "丹东银行");
        put("05406650", "乐山市商业银行");
        put("15567513", "云南祥云渝农商村镇银行");
        put("15567523", "云南鹤庆渝农商村镇银行");
        put("05705500", "华融湘江银行");
        put("28880840", "TheBancorpBank");
        put("15587580", "临沧临翔沪农商村镇银行");
        put("29010410", "新韩卡公司");
        put("15696249", "兴业柳银村镇银行");
        put("15696246", "北流柳银村镇银行");
        put("05625081", "周口银行");
        put("15273752", "天长民生村镇银行");
        put("15072900", "奉贤浦发村镇银行");
        put("15273774", "宁国民生村镇银行");
        put("15195321", "京山中银富登村镇银行");
        put("25180344", "中银信用卡(国际)有限公司");
        put("01020446", "中国工商银行（澳门）");
        put("26620496", "蒙古郭勒姆特银行");
        put("01020276", "中国工商银行法兰克福分行");
        put("01020380", "中国工商银行米兰分行");
        put("03190002", "花旗中国");
        put("03290000", "韩亚银行（中国）");
        put("15083454", "浙江温岭联合村镇银行");
        put("15283310", "浙江萧山湖商村镇银行");
        put("15605053", "灵宝融丰村镇银行");
        put("15403088", "盱眙珠江村镇银行");
        put("15366310", "钦州市钦南国民村镇银行");
        put("64484210", "南昌银行");
        put("05870000", "厦门国际银行");
        put("03020000", "中信银行");
        put("05755200", "湖北银行（宜昌市商业银行）");
        put("65394200", "江西省农村信用社联合社");
        put("14156020", "东莞农村商业银行");
        put("26230446", "大西洋银行股份有限公司");
        put("04512420", "吉林银行（吉林市商业银行）");
        put("03030000", "光大银行");
        put("03080000", "招商银行");
        put("14144500", "山东省农村信用社联合社");
        put("14436100", "广西农村信用社联合社");
        put("04233310", "杭州银行");
        put("05264330", "上饶市商业银行");
        put("03010344", "交通银行香港分行");
        put("03310000", "澳门永亨银行");
        put("04416900", "重庆银行（重庆市商业银行）");
        put("25250446", "大丰银行有限公司");
        put("26330398", "哈萨克斯坦国民储蓄银行");
        put("15406672", "彭山珠江村镇银行");
        put("15915936", "德庆华润村镇银行");
        put("15737012", "息烽包商黔隆村镇银行");
        put("15735556", "武冈包商村镇银行");
        put("15737090", "毕节发展村镇银行");
        put("04192310", "辽阳银行股份有限公司（辽阳市商业银行）");
        put("04462260", "丹东银行股份有限公司（丹东市商业银行）");
        put("25160344", "中信嘉华银行有限公司");
        put("14181000", "北京农村商业银行");
        put("05056020", "东莞商行");
        put("05154680", "德州银行（德州市商业银行）");
        put("15633632", "安徽五河永泰村镇银行");
        put("15405545", "常宁珠江村镇银行");
        put("15194616", "嘉祥中银富登村镇银行");
        put("15203438", "浙江景宁银座村镇银行");
        put("15215521", "株洲县融兴村镇银行");
        put("15216922", "重庆大渡口融兴村镇银行");
        put("05646710", "宜宾市商业银行");
        put("14333051", "太仓农村商业银行");
        put("14367000", "贵州省农村信用社联合社");
        put("05197117", "安顺市城市信用社");
        put("14505800", "广东南海农村商业银行");
        put("26700860", "丝绸之路银行");
        put("27130096", "Baiduri Bank Berhad");
        put("28040586", "巴基斯坦FAYSAL BANK");
        put("01020586", "中国工商银行卡拉奇分行");
        put("15211443", "河间融惠村镇银行");
        put("15464520", "青岛胶南海汇村镇银行");
        put("15033142", "句容茅山村镇银行");
        put("15115893", "广东恩平汇丰村镇银行");
        put("15195288", "枣阳中银富登村镇银行");
        put("15203457", "浙江三门银座村镇银行");
        put("15218242", "会宁会师村镇银行");
        put("15335840", "宝生村镇银行");
        put("15386423", "文昌国民村镇银行");
        put("15438720", "大武口石银村镇银行");
        put("15585511", "长沙星沙沪农商村镇银行");
        put("04885050", "三门峡银行");
        put("01040702", "中行新加坡分行");
        put("64314730", "临商银行");
        put("64916170", "桂林银行");
        put("15587431", "个旧沪农商村镇银行");
        put("15587435", "建水沪农商村镇银行");
        put("29230268", "格鲁吉亚InvestBank");
        put("29460180", "RawbankS.a.r.l");
        put("15455880", "佛山高明顺银村镇银行");
        put("15401000", "北京门头沟珠江村镇银行");
        put("15368841", "哈密红星国民村镇银行");
        put("15273456", "天台民生村镇银行");
        put("15273051", "太仓民生村镇银行");
        put("15271329", "宁晋民生村镇银行");
        put("15055411", "恩施常农商村镇银行");
        put("15204280", "江西赣州银座村镇银行");
        put("15206900", "重庆渝北银座村镇银行");
        put("26530496", "可汗银行");
        put("05167030", "贵州银行（安顺市商业银行）");
        put("05442320", "盘锦银行（盘锦市商业银行）");
        put("05541310", "邢台银行股份有限公司");
        put("04437010", "贵阳银行股份有限公司(贵阳市商业银行)");
        put("03580000", "新网银行");
        put("27650860", "乌兹别克斯坦INFINBANK");
        put("65341770", "临汾市尧都区农信社");
        put("05541310", "邢台银行");
        put("01020360", "中国工商银行（印度尼西亚）");
        put("01020398", "工行阿拉木图");
        put("01020458", "工银马来西亚");
        put("15948032", "陕西洛南阳光村镇银行");
        put("01020826", "工行伦敦");
        put("01040116", "中国银行金边分行");
        put("01040458", "中国银行(马来西亚)");
        put("01040704", "中国银行胡志明分行");
        put("03190001", "花旗银行(中国)有限公司");
        put("03210000", "汇丰银(中国)有限公司");
        put("15083387", "浙江义乌联合村镇银行");
        put("15283361", "浙江德清湖商村镇银行");
        put("05565040", "漯河银行(漯河市商业银行)");
        put("15276914", "潼南民生村镇银行");
        put("04053919", "福建海峡银行");
        put("15731982", "科尔沁包商村镇银行");
        put("15363321", "象山国民村镇银行");
        put("05342050", "鄂尔多斯银行股份有限公司（鄂尔多斯市商业银行）");
        put("04956140", "柳州银行股份有限公司（柳州市商业银行）");
        put("03040000", "华夏银行");
        put("03170000", "渤海银行");
        put("04012900", "上海银行");
        put("5238333", "平凉市城市信用社");
        put("65012900", "上海农村商业银行（上海农商银行）");
        put("03060000", "广东发展银行");
        put("14411200", "河北省农村信用社联合社");
        put("04256020", "东莞银行");
        put("64922690", "龙江银行（大庆市商业银行）");
        put("05303380", "浙江稠州商业银行");
        put("04302249", "抚顺银行");
        put("15736510", "新都桂城村镇银行");
        put("15277491", "景洪民生村镇银行");
        put("14595210", "武汉农村商业银行");
        put("15353117", "江苏东台稠州村镇银行");
        put("16023031", "江苏丰县民丰村镇银行");
        put("16023074", "江苏灌南民丰村镇银行");
        put("64314730", "临商银行（临沂市商业银行）");
        put("14123020", "江阴市农村商业银行");
        put("04221210", "河北银行股份有限公司（石家庄市商业银行）");
        put("25040344", "大新银行有限公司");
        put("04703350", "嘉兴银行（嘉兴市商业银行）");
        put("04991240", "唐山银行");
        put("04478210", "兰州银行股份有限公司（兰州市商业银行）");
        put("15366320", "防城港防城国民村镇银行");
        put("64741910", "内蒙古银行");
        put("64384530", "齐商银行（淄博市商业银行）");
        put("14452400", "吉林省农村信用社联合社");
        put("15283813", "安徽利辛湖商村镇银行");
        put("64895910", "广东南粤银行股份有限公司");
        put("15212629", "延寿融兴村镇银行");
        put("15356900", "重庆北碚稠州村镇银行");
        put("14315850", "珠海农村信用合作社联社");
        put("05864910", "中原银行（安阳商业银行）");
        put("27250608", "菲律宾RCBC");
        put("15604951", "宝丰豫丰村镇银行");
        put("05417900", "长安银行");
        put("05795020", "濮阳银行");
        put("15195287", "老河口中银富登村镇银行");
        put("15585514", "宁乡沪农商行村镇银行");
        put("15572210", "沈阳于洪永安村镇银行");
        put("15775985", "东源泰业村镇银行");
        put("01020702", "中国工商银行新加坡分行");
        put("15567511", "云南大理渝农商村镇银行");
        put("05611480", "衡水银行（衡水市商业银行）");
        put("15587310", "阿拉沪农商村镇银行");
        put("29440480", "CimFinanceLtd");
        put("05556840", "凉山州商业银行");
        put("15354353", "吉安稠州村镇银行");
        put("14448800", "新疆农村信用社联合社");
        put("14572600", "黑龙江省农村信用社联合社");
        put("15173120", "江苏邗江民泰村镇银行");
        put("15194737", "沂水中银富登村镇银行");
        put("15211000", "北京怀柔融兴村镇银行");
        put("15215840", "深圳宝安融兴村镇银行");
        put("05374610", "济宁银行股份有限公司");
        put("05591750", "晋中银行（晋中市商业银行）");
        put("05658880", "库尔勒银行（库尔勒市商业银行）");
        put("64094510", "齐鲁银行股份有限公司");
        put("04901380", "张家口银行（张家口市商业银行）");
        put("01020116", "中国工商银行金边分行");
        put("01020418", "中国工商银行万象分行");
        put("01020442", "中国工商银行卢森堡分行");
        put("01020704", "工行河内");
        put("01020724", "中国工商银行马德里分行");
        put("01040360", "中国银行雅加达分行");
        put("01040410", "中国银行首尔分行");
        put("01040764", "中国银行曼谷分行");
        put("15009028", "石河子交银村镇银行");
        put("15276900", "綦江民生村镇银行");
        put("15476340", "贺州八步东盈村镇银行");
        put("15276880", "资阳民生村镇银行");
        put("15732030", "集宁包商村镇银行");
        put("04966730", "四川天府银行（南充市商业银行）");
        put("01040000", "中国银行");
        put("14055810", "广州农村商业银行");
        put("01020446", "中国工商银行澳门分行");
        put("14468700", "黄河农村商业银行");
        put("05181810", "运城市农村信用合作社联合社");
        put("05247410", "云南红塔银行（玉溪市商业银行）");
        put("05131410", "承德市商业银行");
        put("64296510", "成都市商业银行");
        put("25090344", "上海商业银行");
        put("04083320", "宁波银行（宁波市商业银行）");
        put("04422610", "哈尔滨市银行");
        put("25210344", "集友银行");
        put("05027360", "曲靖市商业银行");
        put("04332350", "葫芦岛银行（葫芦岛市商业银行）");
        put("04721460", "廊坊银行（廊坊市商业银行）");
        put("15278046", "志丹民生村镇银行");
        put("15475950", "惠州仲恺东盈村镇银行");
        put("15735320", "掇刀包商村镇银行");
        put("05478820", "昆仑银行股份有限公司");
        put("14097310", "昆明农联社");
        put("04956140", "柳州银行股份有限公司");
        put("25080344", "星展银行香港有限公司");
        put("15278060", "榆林榆阳民生村镇银行");
        put("14603040", "江南农村商业银行");
        put("16013144", "江苏丹阳保得村镇银行");
        put("16023073", "江苏灌云民丰村镇银行");
        put("04856590", "绵阳市商业银行");
        put("04643970", "泉州银行（泉州市商业银行）");
        put("03110000", "恒丰银行");
        put("04053910", "福建海峡银行股份有限公司（福州市商业银行）");
        put("64624580", "潍坊银行（潍坊市商业银行）");
        put("04302240", "抚顺银行股份有限公司（抚顺市商业银行）");
        put("64135810", "广州银行股份有限公司(广州市商业银行)");
        put("14283054", "江苏苏州农村商业银行（吴江农商行）");
        put("14303050", "苏州银行股份有限公司（江苏东吴农村商业银行股份有限公司）");
        put("04672290", "阜新银行股份有限公司（阜新市商业银行）");
        put("04733450", "泰隆城市信用社");
        put("14163056", "张家港市农村商业银行");
        put("04786110", "南宁市商业银行");
        put("14203320", "鄞州农村合作银行");
        put("25170344", "创兴银行有限公司");
        put("15483023", "宜兴阳羡村镇银行");
        put("01020554", "工银新西兰");
        put("05785800", "广东华兴银行");
        put("15183653", "安徽和县新华村镇银行");
        put("15215373", "洪湖融兴村镇银行");
        put("15315960", "梅县客家村镇银行");
        put("65131410", "承德银行");
        put("05824540", "枣庄银行");
        put("65373020", "无锡农村商业银行");
        put("64303050", "苏州银行");
        put("64422610", "哈尔滨商行");
        put("14341770", "尧都区农村信用合作社联社");
        put("04974634", "莱芜银行");
        put("26040344", "Travelex");
        put("26220446", "澳门国际银行");
        put("05778981", "新疆汇和银行");
        put("99900458", "BankofChina(Malaysia)");
        put("04933160", "江苏长江商业银行");
        put("26550704", "越南Vietcombank");
        put("28660410", "韩国三星卡公司");
        put("15083333", "浙江乐清联合村镇银行");
        put("15083351", "浙江嘉善联合村镇银行");
        put("15195284", "谷城中银富登村镇银行");
        put("15212411", "榆树融兴村镇银行");
        put("15483052", "昆山鹿城村镇银行");
        put("15585623", "涟源沪农商村镇银行");
        put("15585635", "永兴沪农商村镇银行");
        put("15776020", "东莞长安村镇银行");
        put("15357313", "云南安宁稠州村镇银行");
        put("64375850", "珠海华润银行");
        put("48080001", "中银通支付");
        put("15587530", "保山隆阳沪农商村镇银行");
        put("27670643", "RussianStandardBank");
        put("29120496", "CapitalBankofMongolia");
        put("15733129", "仪征包商村镇银行");
        put("05521340", "保定银行");
        put("15494210", "南昌大丰村镇银行");
        put("15403066", "启东珠江村镇银行");
        put("15731922", "固阳包商惠农村镇银行");
        put("15566761", "大竹渝农商村镇银行");
        put("15641100", "天津华明村镇银行");
        put("15511100", "天津武清村镇银行");
        put("14511900", "内蒙古农村信用社联合社");
        put("14538200", "甘肃省农村信用社联合社");
        put("15025371", "湖北仙桃北农商村镇银行");
        put("15036512", "双流诚民村镇银行");
        put("15044015", "福建建瓯石狮村镇银行");
        put("15103352", "浙江平湖工银村镇银行");
        put("15106919", "重庆璧山工银村镇银行");
        put("15116917", "重庆大足汇丰村镇银行");
        put("15123181", "江苏沭阳东吴村镇银行");
        put("15265130", "南阳村镇银行");
        put("26070702", "新加坡大华银行");
        put("05171270", "邯郸银行（邯郸市商业银行）");
        put("04192310", "辽阳银行股份有限公司");
        put("05864910", "许昌银行（许昌市商业银行）");
        put("05631650", "阳泉市商业银行");
        put("64634280", "赣州银行股份有限公司");
        put("15113961", "福建永安汇丰村镇银行");
        put("01020250", "中国工商银行巴黎分行");
        put("01020380", "工行米兰");
        put("01020764", "工银泰国");
        put("01020826", "中国工商银行伦敦子行");
        put("01043320", "中行宁波分行");
        put("03240000", "星展银行");
        put("03280000", "新韩银行");
        put("64221210", "河北银行股份有限公司");
        put("14616410", "海口联合农村商业银行");
        put("15277533", "腾冲民生村镇银行");
        put("15643621", "芜湖泰寿村镇银行");
        put("15947916", "西安高陵阳光村镇银行");
        put("15275323", "钟祥民生村镇银行");
        put("15366230", "银海国民村镇银行");
        put("15404520", "青岛城阳珠江村镇银行");
        put("04403600", "徽商银行");
        put("04791920", "包商银行");
        put("04634280", "赣州银行股份有限公司（赣州市商业银行）");
        put("03100000", "上海浦东发展银行");
        put("03210000", "香港上海汇丰银行有限公司");
        put("05864910", "中原银行");
        put("15406584", "广汉珠江村镇银行");
        put("14163056", "张家港农村商业银行");
        put("15563056", "张家港渝农商村镇银行");
        put("15624916", "新密郑银村镇银行");
        put("15368851", "昌吉国民村镇银行");
        put("15272454", "梅河口民生村镇银行");
        put("15845013", "武陟射阳村镇银行");
        put("14231430", "沧州农信社");
        put("14326030", "中山市农村信用合作社");
        put("04593450", "台州银行（台州市商业银行）");
        put("04588510", "青海银行（西宁市商业银行）");
        put("64733450", "浙江泰隆商业银行");
        put("05484959", "平顶山银行");
        put("15194752", "曹县中银富登村镇银行");
        put("15195379", "监利中银富登村镇银行");
        put("15212723", "桦川融兴村镇银行");
        put("15214931", "偃师融兴村镇银行");
        put("15215547", "耒阳融兴村镇银行");
        put("15356926", "忠县稠州村镇银行");
        put("15406030", "中山东凤珠江村镇银行");
        put("04062410", "吉林银行（长春市商业银行）");
        put("04447910", "西安银行股份有限公司（西安市商业银行）");
        put("04603110", "盐城商行");
        put("14105200", "湖北农信社");
        put("03340000", "大华银行（中国）");
        put("27200704", "越南西贡商业银行");
        put("27520702", "新加坡星网电子付款");
        put("27710418", "BCEL");
        put("28030410", "韩国乐天");
        put("01020124", "中国工商银行加拿大分行");
        put("03360000", "企业银行（中国）");
        put("15438710", "银川掌政石银村镇银行");
        put("15521463", "永清吉银村镇银行");
        put("05755200", "湖北银行");
        put("28530496", "MongoliaTradeDevelop.Bank");
        put("15195375", "潜江中银富登村镇银行");
        put("15206925", "重庆黔江银座村镇银行");
        put("15405895", "鹤山珠江村镇银行");
        put("15535367", "湖北赤壁武弄商村镇银行");
        put("15584713", "阳谷沪农商村镇银行");
        put("15476020", "东莞大朗东盈村镇银行");
        put("25190344", "中国银行（香港）");
        put("15732057", "乌审旗包商村镇银行");
        put("03460000", "重庆富民银行");
        put("15581000", "北京房山沪农商村镇银行");
        put("28020446", "澳门通股份有限公司");
        put("15732053", "准格尔旗包商村镇银行");
        put("15151000", "北京大兴九银村镇银行");
        put("15731000", "北京昌平兆丰村镇银行");
        put("15363323", "宁波市鄞州国民村镇银行");
        put("15115270", "湖北随州曾都汇丰村镇银行");
        put("15145840", "深圳龙岗鼎业村镇银行");
        put("05503320", "宁波东海银行");
        put("05516620", "遂宁银行（遂宁市商业银行）");
        put("05625081", "周口银行");
        put("64384530", "齐商银行");
        put("64392270", "锦州银行");
        put("64624580", "潍坊银行");
        put("25290344", "中国银盛");
        put("01020076", "中国工商银行（巴西）");
        put("01020124", "工行加拿大");
        put("01020360", "中国工商银行(印尼");
        put("04504520", "青岛银行");
        put("01040608", "中国银行马尼拉分行");
        put("03270000", "友利银行(中国)有限公司");
        put("15713386", "浙江兰溪越商村镇银行");
        put("15776314", "灵山泰业村镇银行");
        put("15916260", "百色右江华润村镇银行");
        put("15404560", "福山珠江村镇银行");
        put("15731966", "莫力达瓦包商村镇银行");
        put("15805364", "通城惠民村镇银行");
        put("15696247", "陆川柳银村镇银行");
        put("05121660", "长治银行股份有限公司");
        put("01020000", "中国工商银行");
        put("03090000", "兴业银行");
        put("05121660", "长治银行股份有限公司（长治市商业银行）");
        put("25100344", "永隆银行有限公司");
        put("05253450", "浙江民泰商业银行");
        put("04031000", "北京银行");
        put("14203323", "宁波鄞州农村合作银行");
        put("14293300", "浙江省农村信用社联合社");
        put("65243000", "江苏省农村信用社联合社");
        put("26630410", "BC卡公司");
        put("03160000", "浙商银行");
        put("05274550", "东营银行（东营市商业银行）");
        put("05311930", "乌海银行股份有限公司（乌海市商业银行）");
        put("04991240", "唐山银行（唐山市商业银行）");
        put("14427900", "陕西省农村信用社联合社");
        put("64491610", "晋商银行");
        put("05167030", "贵州银行（六盘水商行）");
        put("04162640", "龙江银行股份有限公司（齐齐哈尔市商业银行)");
        put("04491610", "晋商银行（太原市商业银行）");
        put("15696141", "柳江柳银村镇银行");
        put("15366170", "桂林国民村镇银行");
        put("15275210", "江夏民生村镇银行");
        put("14215881", "佛山市三水区农村信用合作社");
        put("04184930", "洛阳银行（洛阳市商业银行）");
        put("04170000", "盛京银行");
        put("04270001", "乌鲁木齐银行（乌鲁木齐市商业银行）");
        put("14045840", "深圳农村商业银行");
        put("04504520", "青岛银行（青岛市商业银行）");
        put("04753360", "湖州市商业银行");
        put("04256020", "东莞市商业银行");
        put("16023757", "安徽明光民丰村镇银行");
        put("15275251", "宜都民生村镇银行");
        put("14551600", "山西省农村信用社联合社");
        put("05484950", "平顶山银行股份有限公司");
        put("15193754", "全椒中银富登村镇银行");
        put("15194588", "青州中银富登村镇银行");
        put("15194755", "单县中银富登村镇银行");
        put("15216900", "重庆沙坪坝融兴村镇银行");
        put("15216925", "重庆市武隆融兴村镇银行");
        put("04916170", "桂林银行（桂林市商业银行）");
        put("64554770", "日照银行（日照市商业银行）");
        put("04652280", "营口银行股份有限公司（营口市商业银行）");
        put("14353041", "武进农村商业银行");
        put("27240608", "菲律宾BDO");
        put("27550031", "RoyalBank");
        put("28590410", "韩国KB");
        put("48100000", "中银通商务支付有限公司");
        put("64554770", "日照银行");
        put("15404988", "辉县珠江村镇银行");
        put("15436901", "重庆江津石银村镇银行");
        put("05818200", "甘肃银行");
        put("28450643", "俄罗斯ORIENTEXPRESSBANK");
        put("15283315", "浙江建德湖商村镇银行");
        put("15355810", "广州花都稠州村镇银行");
        put("15446610", "广元贵商村镇银行");
        put("15585586", "石门沪农商村镇银行");
        put("15786020", "东莞厚街华业村镇银行");
        put("15214221", "乐平融兴村镇银行");
        put("65264330", "上饶银行");
        put("65385500", "湖南农村信用社联合社");
        put("29170480", "TheMauritiusCommercialBank");
        put("15587432", "开远沪农商村镇银行");
        put("15587433", "蒙自沪农商村镇银行");
        put("15587437", "弥勒沪农商村镇银行");
        put("15641442", "任丘泰寿村镇银行");
        put("15438730", "吴忠市滨河村镇银行");
        put("15845016", "孟州射阳村镇银行");
        put("15738712", "宁夏贺兰回商村镇银行");
        put("14542200", "辽宁省农村信用社联合社");
        put("15006518", "大邑交银兴民村镇银行");
        put("15036753", "宣汉诚民村镇银行");
        put("15083362", "浙江长兴联合村镇银行");
        put("15156030", "中山小榄村镇银行");
        put("26290840", "Discover Financial Services，I");
        put("26320446", "澳门商业银行");
        put("05576750", "达州银行（达州市商业银行）");
        put("05666770", "雅安市商业银行");
        put("05864910", "中原银行（商丘商行）");
        put("64786110", "广西北部湾银行");
        put("15183772", "郎溪新华村镇银行");
        put("65097300", "云南省农村信用社");
        put("04761430", "沧州银行");
        put("01020056", "工行布鲁塞尔");
        put("01020056", "中国工商银行布鲁塞尔分行");
        put("01020392", "工行东京分行");
        put("01020458", "工行马来西亚");
        put("01020704", "工银河内");
        put("01033320", "宁波市农业银行");
        put("15273790", "池州贵池民生村镇银行");
        put("15515134", "河南方城凤裕村镇银行");
        put("15731611", "清徐惠民村镇银行");
        put("04375850", "珠海华润银行股份有限公司（珠海市商业银行股份有限公司）");
        put("15563956", "福建沙县渝农商村镇银行");
        put("04571260", "秦皇岛银行股份有限公司(秦皇岛市商业银行)");
        put("15404569", "莱州珠江村镇银行");
        put("15404790", "莱芜珠江村镇银行");
        put("15732017", "西乌珠穆沁包商惠丰村镇银行");
        put("04447910", "西安银行股份有限公司");
        put("15752281", "辽宁大石桥隆丰村镇银行");
        put("15734759", "鄄城包商村镇银行");
        put("15625033", "鄢陵郑银村镇银行");
        put("15522410", "长春双阳吉银村镇银行");
        put("15273113", "阜宁民生村镇银行");
        put("04562239", "鞍山银行");
        put("04986580", "德阳银行（德阳市商业银行）");
        put("14265930", "肇庆农村信用社");
        put("14473600", "安徽省农村信用社联合社");
        put("01040446", "中国银行澳门分行");
        put("14486400", "海南省农村信用社联合社");
        put("26690643", "莫斯科人民储蓄银行");
        put("04123330", "温州银行");
        put("14191100", "天津市农村信用社");
        put("15776927", "重庆开州泰业村镇银行股份有限公司（曾用名：开县泰业村镇银行）");
        put("15654924", "开封新东方村镇银行");
        put("04836560", "攀枝花市商业银行");
        put("15406522", "新津珠江村镇银行");
        put("05734220", "景德镇商业银行");
        put("15773683", "枞阳泰业村镇银行");
        put("16023010", "江苏溧水民丰村镇银行");
        put("65226510", "成都农村商业银行");
        put("04871620", "大同银行（大同市商业银行）");
        put("03134650", "威海市商业银行");
        put("04523060", "江苏银行（南通市商业银行）");
        put("04341100", "天津银行（天津市商业银行）");
        put("04885050", "三门峡市城市信用社");
        put("14023052", "昆山农村信用合作社联合社");
        put("04895910", "广东南粤银行（湛江市商业银行）");
        put("04283370", "绍兴银行股份有限公司（绍兴市商业银行）");
        put("04243010", "南京银行");
        put("04213050", "苏州市商业银行");
        put("14275880", "佛山市禅城区农村信用联社");
        put("65085883", "佛山顺德农村商业银行");
        put("05031680", "晋城银行股份有限公司（晋城商业银行）");
        put("04484210", "江西银行（南昌市商业银行）");
        put("15404960", "安阳珠江村镇银行");
        put("14033055", "常熟农村商业银行");
        put("15366264", "平果国民村镇银行");
        put("15183687", "望江新华村镇银行");
        put("15194689", "临邑中银富登村镇银行");
        put("15215352", "应城融兴村镇银行");
        put("15216620", "遂宁安居融兴村镇银行");
        put("15216935", "重庆市酋阳融兴村镇银行");
        put("15343116", "江苏大丰江南村镇银行");
        put("03134560", "烟台银行（烟台市商业银行）");
        put("04023930", "厦门银行股份有限公司");
        put("14561100", "天津滨海农村商业银行");
        put("05767700", "西藏银行");
        put("15514550", "东营莱商村镇银行");
        put("15584712", "临清沪农商村镇银行");
        put("15584715", "茌平沪农商村镇银行");
        put("15585541", "衡阳沪农商村镇银行");
        put("15585584", "临澧沪农商村镇银行");
        put("15585634", "桂阳沪农商村镇银行");
        put("05311930", "乌海银行股份有限公司");
        put("15732415", "九台龙嘉村镇银行");
        put("15567571", "云南香格里拉渝农商村镇银行");
        put("15476061", "云浮新兴东盈民生村镇银行");
        put("64588510", "青海银行");
        put("15436900", "重庆南川石银村镇银行");
        put("27860446", "澳门BDA");
        put("15695812", "从化柳银村镇银行");
        put("15732036", "化德包商村镇银行");
        put("15366110", "南宁江南国民村镇银行");
        put("15366231", "合浦国民村镇银行");
        put("15015363", "湖北嘉鱼吴江村镇银行");
        put("15024521", "青岛即墨北农商村镇银行");
        put("15036410", "海口苏南村镇银行");
        put("15055416", "咸丰常农商村镇银行");
        put("15195338", "蕲春中银富登村镇银行");
        put("15201000", "北京顺义银座村镇银行");
        put("25070344", "建设银行亚洲公司");
        put("25270446", "建设银行澳门公司");
        put("26350764", "Bangkok Bank Pcl");
        put("05417930", "宝鸡商行");
        put("05426900", "重庆三峡银行");
        put("05864910", "中原银行（新乡市商业银行）");
        put("64667310", "富滇银行");
        put("64753360", "湖州银行");
        put("65274550", "东营银行");
        put("01020360", "工银印尼");
        put("01020398", "中国工商银行阿拉木图子行");
        put("01020724", "工行马德里");
        put("01040036", "中国银行（澳大利亚）");
        put("01040392", "中银东京分行");
        put("03220000", "渣打银行中国有限公司");
        put("03300000", "华侨永亨银行（中国）");
        put("25060344", "华侨永亨银行股份有限公司");
        put("15735040", "漯河市郾城包商村镇银行");
        put("15369028", "石河子国民村镇银行");
        put("15696158", "融水柳银村镇银行");
        put("05516629", "遂宁银行（遂宁市商业银行）");
        put("15731971", "鄂温克旗包商村镇银行");
        put("15274986", "长垣民生村镇银行");
        put("15655031", "长葛轩辕村镇银行");
        put("05605128", "驻马店银行");
        put("03070000", "平安银行");
        put("05083000", "江苏银行");
        put("14136530", "重庆市农村信用社联合社");
        put("14173900", "福建省农村信用社联合社");
        put("04360010", "宁夏银行");
        put("03010000", "交通银行");
        put("05167030", "贵州银行（遵义市商业银行）");
        put("04615510", "长沙银行股份有限公司（长沙市商业银行）");
        put("03050000", "中国民生银行");
        put("26110392", "日本三井住友卡公司");
        put("04296510", "成都银行（成都商业银行）");
        put("14526500", "四川省农村信用社联合社");
        put("01000000", "中国邮政储蓄银行");
        put("65154680", "德州银行");
        put("05492340", "朝阳银行");
        put("15733062", "江苏南通如皋包商村镇银行");
        put("15184299", "江西兴国新华村镇银行");
        put("04866570", "泸州银行（泸州市商业银行）");
        put("04023930", "厦门银行股份有限公司（厦门市商业银行）");
        put("04073140", "镇江市商业银行");
        put("15274561", "蓬莱民生村镇银行");
        put("03260000", "恒生银行有限公司");
        put("04544240", "九江银行股份有限公司（九江市商业银行）");
        put("04667310", "昆明商业银行");
        put("15283688", "安徽粤西湖商村镇银行");
        put("15283812", "安徽蒙城湖商村镇银行");
        put("15884583", "山东临朐聚丰村镇银行");
        put("15181123", "天津静海新华村镇银行");
        put("15193320", "宁波镇海中银富登村镇银行");
        put("15193322", "宁海中银富登村镇银行");
        put("15193753", "来安中银富登村镇银行");
        put("15212625", "巴彦融兴村镇银行");
        put("15213063", "江苏如东融兴村镇银行");
        put("15273974", "安溪民生村镇银行");
        put("15405150", "信阳珠江村镇银行");
        put("04922600", "龙江银行");
        put("05326560", "自贡市商业银行");
        put("05748840", "哈密市商业银行");
        put("05832250", "本溪银行（本溪市商业银行）");
        put("14024510", "山东省农联社");
        put("14105210", "武汉农信");
        put("04652280", "营口银行股份有限公司");
        put("04354910", "郑州银行股份有限公司（郑州市商业银行）");
        put("04933120", "靖江市长江城市信用社");
        put("03350000", "大新银行（中国）");
        put("14255890", "江门新会农村商业银行");
        put("26780643", "俄罗斯远东商业银行");
        put("26790422", "CSC");
        put("26930608", "Allied Bank");
        put("28720762", "CJSCFononbank");
        put("65191100", "天津农村商业银行");
        put("14293300", "杭州联合银行");
        put("05438720", "石嘴山银行");
        put("28550764", "KrungThajBankPublicCo.Ltd");
        put("28990586", "巴基斯坦HabibBank");
        put("15185810", "广州番禹新华村镇银行");
        put("15212652", "拜泉融兴村镇银行");
        put("15216437", "海南保亭融兴村镇银行");
        put("15386424", "琼海国民村镇银行");
        put("15535360", "湖北咸安武农商村镇银行");
        put("15535813", "广州增城长江村镇银行");
        put("15584513", "济南槐荫沪农商村镇银行");
        put("15584710", "聊城东昌沪农商村镇银行");
        put("15584770", "日照沪农商村镇银行");
        put("15585583", "澧县沪农商村镇银行");
        put("15585591", "慈利沪农商村镇银行");
        put("15587317", "嵩明沪农商村镇银行");
        put("25020344", "东亚银行有限公司");
        put("15366322", "东兴国民村镇银行");
        put("04974790", "莱商银行");
        put("15585840", "深圳光明沪农商村镇银行");
        put("15587546", "瑞丽沪农商村镇银行");
        put("05695150", "信阳银行");
        put("15696248", "博白柳银村镇银行");
        put("15732220", "大连金州联丰村镇银行");
        put("15731100", "天津津南村镇银行");
        put("15731948", "宁城包商村镇银行");
        put("04083320", "宁波银行");
        put("15111027", "北京密云汇丰村镇银行");
        put("15142080", "方大村镇银行");
        put("15183651", "安徽当涂新华村镇银行");
        put("15205840", "深圳福田银座村镇银行");
        put("05354970", "鹤壁银行");
        put("05392330", "铁岭银行");
        put("05864910", "中原银行（驻马店银行）");
        put("64544240", "九江银行股份有限公司");
        put("05864910", "中原银行（商丘市商业银行）");
        put("15272900", "上海松江民生村镇银行");
        put("01020276", "工银法兰克福");
        put("01020410", "工行首尔");
        put("03010446", "交通银行澳门分行");
        put("03080344", "招商银行香港分行");
        put("15523120", "江都吉银村镇银行");
        put("04184930", "洛阳银行");
        put("15083412", "浙江常山联合村镇银行");
        put("15404564", "海阳珠江村镇银行");
        put("15273993", "漳浦民生村镇银行");
        put("03410000", "浙江网商银行");
    }};

    private static ImageDTO getImageBse64WithUrl(String imageUrl) {
        ImageDTO imageDTO = new ImageDTO();
        try {
            URL url = new URL(imageUrl);
            // 读取文件的前几个字节（这里假设判断文件类型只需读取前两个字节）
            try (InputStream inputStream = url.openStream()) {
                byte[] bytes = org.apache.commons.io.IOUtils.toByteArray(inputStream);
                // 根据读取到的字节进行判断
                int b1 = bytes[0] & 0xFF;
                int b2 = bytes[1] & 0xFF;
                String imageFormat = getImageFormat(b1, b2);
                imageDTO.setType(imageFormat);
                String base64 = org.apache.commons.codec.binary.Base64.encodeBase64String(bytes);
                imageDTO.setBase64(base64);
            }
        } catch (Exception e) {
            throw new GlobalRunTimeException("图片获取失败");
        }
        return imageDTO;
    }

    // 根据文件头部的字节判断图片格式
    private static String getImageFormat(int b1, int b2) {
        if (b1 == 0xFF && b2 == 0xD8) {
            return "JPEG";
        } else if (b1 == 0x89 && b2 == 0x50) {
            return "PNG";
        } else if (b1 == 0x47 && b2 == 0x49) {
            return "GIF";
        } else if (b1 == 0x42 && b2 == 0x4D) {
            return "BMP";
        } else {
            throw new GlobalRunTimeException("图片格式解析失败");
        }
    }


}

@Data
class ImageDTO {
    private String type;
    private String base64;

}